Comparing version 3.1.2 to 4.0.0
@@ -5,2 +5,18 @@ # Change Log | ||
<a name="4.0.0"></a> | ||
# [4.0.0](https://github.com/untool/mixinable/compare/v3.1.2...v4.0.0) (2018-08-17) | ||
### Code Refactoring | ||
* significantly simplify implementation ([573ead8](https://github.com/untool/mixinable/commit/573ead8)) | ||
### BREAKING CHANGES | ||
* remove function/class/constructor support for | ||
strategies definition, remove hash support for mixin definitions | ||
<a name="3.1.2"></a> | ||
@@ -7,0 +23,0 @@ ## [3.1.2](https://github.com/untool/mixinable/compare/v3.1.1...v3.1.2) (2018-07-24) |
124
index.js
@@ -5,6 +5,25 @@ 'use strict'; | ||
module.exports = exports = function define(strategies) { | ||
return function mixin() { | ||
var mixins = argsToArray(arguments).map(createMixin); | ||
return createMixinable(strategies, mixins); | ||
module.exports = exports = function define(strategies, mixins) { | ||
return function Mixinable() { | ||
var args = argsToArray(arguments); | ||
if (!(this instanceof Mixinable)) { | ||
return new (bindArgs(Mixinable, args))(); | ||
} | ||
var mixinstances = (mixins || []).map(function(Mixin) { | ||
return new (bindArgs(Mixin, args))(); | ||
}); | ||
Object.keys(strategies || {}).forEach(function(method) { | ||
this[method] = strategies[method].bind( | ||
this, | ||
mixinstances.reduce(function(functions, mixinstance) { | ||
if (isFunction(mixinstance[method])) { | ||
functions.push(mixinstance[method].bind(mixinstance)); | ||
} | ||
return functions; | ||
}, []) | ||
); | ||
mixinstances.forEach(function(mixinstance) { | ||
mixinstance[method] = this[method]; | ||
}, this); | ||
}, this); | ||
}; | ||
@@ -88,97 +107,2 @@ }; | ||
// core functions | ||
function createMixin(definition) { | ||
if (isFunction(definition)) { | ||
return definition; | ||
} | ||
function Mixin() { | ||
getConstructor(definition).apply(this, arguments); | ||
} | ||
Mixin.prototype = Object.create(getPrototype(definition)); | ||
Mixin.prototype.constructor = Mixin; | ||
return Mixin; | ||
} | ||
function createMixinable(strategies, mixins) { | ||
function Mixinable() { | ||
var args = argsToArray(arguments); | ||
if (!(this instanceof Mixinable)) { | ||
return new (bindArgs(Mixinable, args))(); | ||
} | ||
getConstructor(strategies).apply(this, args); | ||
bootstrapMixinable( | ||
this, | ||
mixins.map(function(Mixin) { | ||
return new (bindArgs(Mixin, args))(); | ||
}) | ||
); | ||
} | ||
Mixinable.prototype = Object.create(getPrototype(strategies)); | ||
Mixinable.prototype.constructor = Mixinable; | ||
return Mixinable; | ||
} | ||
function bootstrapMixinable(mixinable, mixinstances) { | ||
mixinstances.forEach(bindMethods); | ||
getMethodNames(mixinable).forEach(function(method) { | ||
mixinable[method] = mixinable[method].bind( | ||
mixinable, | ||
mixinstances.reduce(function(functions, mixinstance) { | ||
if (isFunction(mixinstance[method])) { | ||
functions.push(mixinstance[method]); | ||
} | ||
return functions; | ||
}, []) | ||
); | ||
mixinstances.forEach(function(mixinstance) { | ||
mixinstance[method] = mixinable[method]; | ||
}); | ||
}); | ||
} | ||
// classy helpers | ||
function getConstructor(obj) { | ||
if (isFunction(obj)) { | ||
return obj; | ||
} | ||
if (obj && obj.hasOwnProperty('constructor')) { | ||
return obj.constructor; | ||
} | ||
return function() {}; | ||
} | ||
function getPrototype(obj) { | ||
if (isFunction(obj) && obj.hasOwnProperty('prototype')) { | ||
return obj.prototype; | ||
} | ||
return obj || Object.create(null); | ||
} | ||
function bindMethods(obj) { | ||
getMethodNames(obj).forEach(function(method) { | ||
obj[method] = obj[method].bind(obj); | ||
}); | ||
return obj; | ||
} | ||
function getMethodNames(obj) { | ||
return getPropertyNames(obj).filter(function(prop) { | ||
return prop !== 'constructor' && typeof obj[prop] === 'function'; | ||
}); | ||
} | ||
function getPropertyNames(obj) { | ||
var props = []; | ||
do { | ||
Object.getOwnPropertyNames(obj || {}).forEach(function(prop) { | ||
if (props.indexOf(prop) === -1) { | ||
props.push(prop); | ||
} | ||
}); | ||
} while ((obj = Object.getPrototypeOf(obj || {})) !== Object.prototype); | ||
return props; | ||
} | ||
// utilities | ||
@@ -195,3 +119,3 @@ | ||
function bindArgs(fn, args) { | ||
return Function.prototype.bind.apply(fn, [fn].concat(args)); | ||
return Function.prototype.bind.apply(fn, [null].concat(args)); | ||
} | ||
@@ -198,0 +122,0 @@ |
{ | ||
"name": "mixinable", | ||
"version": "3.1.2", | ||
"version": "4.0.0", | ||
"description": "Functional JavaScript Mixin Utility", | ||
@@ -37,3 +37,3 @@ "main": "index.js", | ||
"eslint": "^5.0.0", | ||
"eslint-config-prettier": "^2.9.0", | ||
"eslint-config-prettier": "^3.0.0", | ||
"eslint-plugin-prettier": "^2.6.0", | ||
@@ -40,0 +40,0 @@ "husky": "^0.14.3", |
160
README.md
@@ -7,6 +7,4 @@ # mixinable | ||
Mixins are plain Objects (or hashes) that can easily be shared, modified and extended using standard language features such as [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Spread_in_object_literals) or [`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). | ||
Mixins are usually classes that can easily be shared, modified and extended using standard language features. `mixinable` supports asynchronous methods returning [`Promises`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promises). | ||
`mixinable` allows you to provide custom [`constructor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) functions and supports asynchronous methods returning [`Promises`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promises). It is built in a functional way, allowing you to, for example, apply [`fn.bind()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). | ||
### Installation | ||
@@ -30,10 +28,6 @@ | ||
#### `define(definition)` | ||
#### `define(definition, mixins)` | ||
The main export of `mixinable` is a `define()` function accepting a mixin container definition. This definition hash is made up of `strategy` functions prescribing how to handle different mixin methods you provide. | ||
The main export of `mixinable` is a `define()` function accepting a mixin container definition and an array of mixins, i.e. classes. The definition hash is made up of `strategy` functions prescribing how to handle different mixin methods you provide. It returns a `create()` function that accepts whatever arguments your mixins' `constructor()`s accept. | ||
It returns a variadic `mixin()` function that accepts the mixin definitions you want to apply and returns a `create()` function. Mixin definitions are hashes containing mixin method implementations that are being applied using the aforementioned strategies. | ||
And that `create()` function accepts whatever arguments your `constructor()`s accept. | ||
##### Example | ||
@@ -44,16 +38,19 @@ | ||
const mixin = define({ | ||
// mixin strategy function | ||
bar(functions, arg) { | ||
return functions.pop()(arg); | ||
const create = define( | ||
{ | ||
// mixin strategy function | ||
bar(functions, arg) { | ||
return functions.pop()(arg); | ||
}, | ||
}, | ||
}); | ||
[ | ||
// mixin implementation | ||
class { | ||
bar(arg) { | ||
console.log(arg); | ||
}, | ||
} | ||
] | ||
); | ||
const create = mixin({ | ||
// mixin implementation | ||
bar(arg) { | ||
console.log(arg); | ||
}, | ||
}); | ||
const foo = create(); | ||
@@ -74,19 +71,23 @@ | ||
const mixin = define({ | ||
bar(functions, arg) { | ||
return functions.pop()(arg); | ||
const create = define( | ||
{ | ||
bar(functions, arg) { | ||
return functions.pop()(arg); | ||
}, | ||
}, | ||
}); | ||
[ | ||
// mixin implementations | ||
class { | ||
// public mixin method | ||
bar(arg) { | ||
this.qux(arg); | ||
}, | ||
// private mixin method | ||
qux(arg) { | ||
console.log(arg); | ||
}, | ||
} | ||
] | ||
); | ||
const create = mixin({ | ||
// mixin method implementations | ||
bar(arg) { | ||
this.qux(arg); | ||
}, | ||
// private mixin method | ||
qux(arg) { | ||
console.log(arg); | ||
}, | ||
}); | ||
const foo = create(); | ||
@@ -108,11 +109,4 @@ | ||
const mixin = define(); | ||
const create = mixin( | ||
const create = define({}, [ | ||
// mixin contructors | ||
{ | ||
constructor: function(arg) { | ||
console.log(arg); | ||
}, | ||
}, | ||
class { | ||
@@ -122,8 +116,7 @@ constructor(arg) { | ||
} | ||
} | ||
); | ||
}, | ||
]); | ||
create('yee-hah!'); | ||
// yee-hah! | ||
// yee-hah! | ||
``` | ||
@@ -140,13 +133,11 @@ | ||
const mixin = define({ | ||
const create = define({ | ||
// mixin strategy function | ||
bar: override, | ||
}); | ||
const create = mixin( | ||
// mixin method implementations | ||
{ | ||
}, [ | ||
// mixin implementations | ||
class { | ||
bar() { | ||
console.log(1); | ||
}, | ||
} | ||
}, | ||
@@ -157,4 +148,4 @@ class { | ||
} | ||
} | ||
); | ||
}, | ||
]); | ||
@@ -180,13 +171,11 @@ const foo = create(); | ||
const mixin = define({ | ||
const create = define({ | ||
// mixin strategy function | ||
bar: parallel, | ||
}); | ||
const create = mixin( | ||
// mixin method implementations | ||
{ | ||
}, [ | ||
// mixin implementations | ||
class { | ||
bar(val, inc) { | ||
return Promise.resolve(val + inc); | ||
}, | ||
return val + inc; | ||
} | ||
}, | ||
@@ -197,4 +186,4 @@ class { | ||
} | ||
} | ||
); | ||
}, | ||
]); | ||
@@ -220,13 +209,11 @@ const foo = create(); | ||
const mixin = define({ | ||
const create = define({ | ||
// mixin strategy function | ||
bar: pipe, | ||
}); | ||
const create = mixin( | ||
// mixin method implementations | ||
{ | ||
}, [ | ||
// mixin implementations | ||
class { | ||
bar(val, inc) { | ||
return Promise.resolve(val + inc); | ||
}, | ||
return val + inc; | ||
} | ||
}, | ||
@@ -237,4 +224,4 @@ class { | ||
} | ||
} | ||
); | ||
}, | ||
]); | ||
@@ -261,5 +248,6 @@ const foo = create(); | ||
bar: compose, | ||
}); | ||
// ... | ||
}, [ | ||
// mixin implementations | ||
// ... | ||
]); | ||
``` | ||
@@ -283,10 +271,10 @@ | ||
}, | ||
}); | ||
const create = mixin({ | ||
// mixin method implementation | ||
bar(arg) { | ||
console.log(arg); | ||
}, [ | ||
// mixin implementation | ||
class { | ||
bar(arg) { | ||
console.log(arg); | ||
}, | ||
}, | ||
}); | ||
]); | ||
@@ -293,0 +281,0 @@ const foo = create(); |
847
test.js
@@ -31,7 +31,5 @@ 'use strict'; | ||
test('basic function test', function(t) { | ||
t.plan(3); | ||
var mixin = mixinable(); | ||
t.is(typeof mixin, 'function', 'mixinable creates a mixin function'); | ||
var create = mixin(); | ||
t.is(typeof create, 'function', 'mixin creates a create function'); | ||
t.plan(2); | ||
var create = mixinable(); | ||
t.is(typeof create, 'function', 'mixinable creates a create function'); | ||
var result = create(); | ||
@@ -42,52 +40,20 @@ t.truthy(result, 'create returns something'); | ||
test('constructor support test', function(t) { | ||
t.plan(4); | ||
t.plan(3); | ||
var arg = 1; | ||
mixinable({ | ||
constructor: function(_arg) { | ||
t.is(_arg, arg, 'facade receives correct arg'); | ||
mixinable({}, [ | ||
function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
}, | ||
})( | ||
{ | ||
constructor: function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
}, | ||
function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
}, | ||
{ | ||
constructor: function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
}, | ||
function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
}, | ||
{ | ||
constructor: function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
}, | ||
} | ||
)(arg); | ||
])(arg); | ||
}); | ||
test('inheritance test', function(t) { | ||
t.plan(15); | ||
t.plan(8); | ||
var arg = 1; | ||
function Strategy(_arg) { | ||
t.pass('strategy constructor is being called'); | ||
t.is(_arg, arg, 'strategy constructor receives correct arg'); | ||
t.true(this instanceof Strategy, 'strategy inherits correctly'); | ||
t.true( | ||
Strategy.prototype.isPrototypeOf(this), | ||
'strategy prototype chain is set up' | ||
); | ||
} | ||
Strategy.prototype = { | ||
foo: function(functions, _arg) { | ||
t.is(_arg, arg, 'strategy definition receives correct arg'); | ||
t.true(this instanceof Strategy, 'strategy inherits correctly'); | ||
t.true( | ||
Strategy.prototype.isPrototypeOf(this), | ||
'strategy prototype chain is set up' | ||
); | ||
functions.forEach(function(fn) { | ||
fn(_arg); | ||
}); | ||
}, | ||
}; | ||
function Implementation(_arg) { | ||
@@ -116,3 +82,3 @@ t.pass('implementation constructor is being called'); | ||
}; | ||
var instance = mixinable(Strategy)(Implementation)(arg); | ||
var instance = mixinable({ foo: mixinable.override }, [Implementation])(arg); | ||
instance.foo(arg); | ||
@@ -124,21 +90,30 @@ }); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.callable, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function() { | ||
t.fail('1st implementation should not be called'); | ||
}, | ||
foo: mixinable.callable, | ||
}, | ||
{ | ||
foo: function() { | ||
t.fail('2nd implementation should not be called'); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.fail('1st implementation should not be called'); | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.pass('3rd implementation is being called'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.fail('2nd implementation should not be called'); | ||
}, | ||
}); | ||
}, | ||
} | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.pass('3rd implementation is being called'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
}, | ||
}); | ||
}, | ||
] | ||
)(); | ||
@@ -151,21 +126,30 @@ instance.foo(arg); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.override, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function() { | ||
t.fail('1st implementation should not be called'); | ||
}, | ||
foo: mixinable.override, | ||
}, | ||
{ | ||
foo: function() { | ||
t.fail('2nd implementation should not be called'); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.fail('1st implementation should not be called'); | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.pass('3rd implementation is being called'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.fail('2nd implementation should not be called'); | ||
}, | ||
}); | ||
}, | ||
} | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.pass('3rd implementation is being called'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
}, | ||
}); | ||
}, | ||
] | ||
)(); | ||
@@ -179,38 +163,47 @@ instance.foo(arg); | ||
var ctr = 0; | ||
var instance = mixinable({ | ||
foo: mixinable.parallel, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
t.is(ctr, 0, '1st implementation is being called first'); | ||
this.increment(); | ||
}, | ||
increment: function() { | ||
t.pass('1st private method is being called'); | ||
++ctr; | ||
}, | ||
foo: mixinable.parallel, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
t.is(ctr, 1, '2nd implementation is being called second'); | ||
this.increment(); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
t.is(ctr, 0, '1st implementation is being called first'); | ||
this.increment(); | ||
}, | ||
increment: function() { | ||
t.pass('1st private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function() { | ||
t.pass('2nd private method is being called'); | ||
++ctr; | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
t.is(ctr, 1, '2nd implementation is being called second'); | ||
this.increment(); | ||
}, | ||
increment: function() { | ||
t.pass('2nd private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
t.is(ctr, 2, '3rd implementation is being called third'); | ||
this.increment(); | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
t.is(ctr, 2, '3rd implementation is being called third'); | ||
this.increment(); | ||
}, | ||
increment: function() { | ||
t.pass('3rd private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function() { | ||
t.pass('3rd private method is being called'); | ||
++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -224,59 +217,68 @@ instance.foo(arg); | ||
var ctr = 0; | ||
var instance = mixinable({ | ||
foo: mixinable.parallel, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
t.is(ctr, 0, '1st implementation is being called instantaneously'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
this.increment(); | ||
resolve(ctr); | ||
}.bind(this), | ||
10 | ||
foo: mixinable.parallel, | ||
}, | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
t.is(ctr, 0, '1st implementation is being called instantaneously'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
this.increment(); | ||
resolve(ctr); | ||
}.bind(this), | ||
10 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function() { | ||
t.pass('1st private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function() { | ||
t.pass('1st private method is being called'); | ||
++ctr; | ||
}, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
t.is(ctr, 0, '2nd implementation is being called instantaneously'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
this.increment(); | ||
resolve(ctr); | ||
}.bind(this), | ||
5 | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
t.is(ctr, 0, '2nd implementation is being called instantaneously'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
this.increment(); | ||
resolve(ctr); | ||
}.bind(this), | ||
5 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function() { | ||
t.pass('2nd private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function() { | ||
t.pass('2nd private method is being called'); | ||
++ctr; | ||
function() { | ||
Object.assign(this, { | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
t.is(ctr, 0, '3rd implementation is being called instantaneously'); | ||
this.increment(); | ||
return ctr; | ||
}, | ||
increment: function() { | ||
t.pass('3rd private method is being called'); | ||
++ctr; | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(_arg) { | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
t.is(ctr, 0, '3rd implementation is being called instantaneously'); | ||
this.increment(); | ||
return ctr; | ||
}, | ||
increment: function() { | ||
t.pass('3rd private method is being called'); | ||
++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -296,38 +298,47 @@ var result = instance.foo(arg); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.pipe, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '1st implementation receives inital value'); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
foo: mixinable.pipe, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '1st implementation receives inital value'); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "3rd implementation receives 2nd's result"); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "3rd implementation receives 2nd's result"); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -340,56 +351,65 @@ t.is(instance.foo(0, arg), 3, 'correct result received'); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.pipe, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '1st implementation receives inital value'); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
10 | ||
foo: mixinable.pipe, | ||
}, | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '1st implementation receives inital value'); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
10 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
5 | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
5 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "3rd implementation receives 2nd's result"); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "3rd implementation receives 2nd's result"); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -406,38 +426,47 @@ var result = instance.foo(0, arg); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.compose, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "1st implementation receives 2nd's result"); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
foo: mixinable.compose, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "1st implementation receives 2nd's result"); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '3rd implementation receives inital value'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '3rd implementation receives inital value'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -450,56 +479,65 @@ t.is(instance.foo(0, arg), 3, 'correct result received'); | ||
var arg = 1; | ||
var instance = mixinable({ | ||
foo: mixinable.compose, | ||
})( | ||
var instance = mixinable( | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "1st implementation receives 2nd's result"); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
foo: mixinable.compose, | ||
}, | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 2, "1st implementation receives 2nd's result"); | ||
t.is(_arg, arg, '1st implementation receives correct arg'); | ||
return this.increment(ctr); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('1st private method is being called'); | ||
return ++ctr; | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
5 | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 1, "2nd implementation receives 1st's result"); | ||
t.is(_arg, arg, '2nd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
5 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('2nd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}, | ||
{ | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '3rd implementation receives inital value'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
10 | ||
function() { | ||
Object.assign(this, { | ||
foo: function(ctr, _arg) { | ||
t.is(ctr, 0, '3rd implementation receives inital value'); | ||
t.is(_arg, arg, '3rd implementation receives correct arg'); | ||
return new Promise( | ||
function(resolve) { | ||
setTimeout( | ||
function() { | ||
resolve(this.increment(ctr)); | ||
}.bind(this), | ||
10 | ||
); | ||
}.bind(this) | ||
); | ||
}.bind(this) | ||
); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
}); | ||
}, | ||
increment: function(ctr) { | ||
t.pass('3rd private method is being called'); | ||
return ++ctr; | ||
}, | ||
} | ||
] | ||
)(); | ||
@@ -515,13 +553,20 @@ var result = instance.foo(0, arg); | ||
t.plan(4); | ||
var instance = mixinable({ | ||
foo: async.override, | ||
bar: async.parallel, | ||
baz: async.pipe, | ||
qux: async.compose, | ||
})({ | ||
foo: function() {}, | ||
bar: function() {}, | ||
baz: function() {}, | ||
qux: function() {}, | ||
})(); | ||
var instance = mixinable( | ||
{ | ||
foo: async.override, | ||
bar: async.parallel, | ||
baz: async.pipe, | ||
qux: async.compose, | ||
}, | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() {}, | ||
bar: function() {}, | ||
baz: function() {}, | ||
qux: function() {}, | ||
}); | ||
}, | ||
] | ||
)(); | ||
t.true(instance.foo() instanceof Promise, 'override result is a promise'); | ||
@@ -535,25 +580,32 @@ t.true(instance.bar() instanceof Promise, 'parallel result is a promise'); | ||
t.plan(5); | ||
var instance = mixinable({ | ||
foo: sync.override, | ||
bar: sync.parallel, | ||
baz: sync.pipe, | ||
qux: sync.sequence, | ||
quz: sync.compose, | ||
})({ | ||
foo: function() { | ||
return Promise.resolve(); | ||
var instance = mixinable( | ||
{ | ||
foo: sync.override, | ||
bar: sync.parallel, | ||
baz: sync.pipe, | ||
qux: sync.sequence, | ||
quz: sync.compose, | ||
}, | ||
bar: function() { | ||
return Promise.resolve(); | ||
}, | ||
baz: function() { | ||
return Promise.resolve(); | ||
}, | ||
qux: function() { | ||
return Promise.resolve(); | ||
}, | ||
quz: function() { | ||
return Promise.resolve(); | ||
}, | ||
})(); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
return Promise.resolve(); | ||
}, | ||
bar: function() { | ||
return Promise.resolve(); | ||
}, | ||
baz: function() { | ||
return Promise.resolve(); | ||
}, | ||
qux: function() { | ||
return Promise.resolve(); | ||
}, | ||
quz: function() { | ||
return Promise.resolve(); | ||
}, | ||
}); | ||
}, | ||
] | ||
)(); | ||
t.throws( | ||
@@ -588,17 +640,24 @@ instance.foo.bind(instance), | ||
t.plan(2); | ||
var create = mixinable({ | ||
foo: mixinable.override, | ||
bar: mixinable.override, | ||
})( | ||
var create = mixinable( | ||
{ | ||
foo: function() { | ||
t.pass('first method is being called'); | ||
this.bar(); | ||
}, | ||
foo: mixinable.override, | ||
bar: mixinable.override, | ||
}, | ||
{ | ||
bar: function() { | ||
t.pass('second method is being called'); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.pass('first method is being called'); | ||
this.bar(); | ||
}, | ||
}); | ||
}, | ||
} | ||
function() { | ||
Object.assign(this, { | ||
bar: function() { | ||
t.pass('second method is being called'); | ||
}, | ||
}); | ||
}, | ||
] | ||
); | ||
@@ -610,42 +669,28 @@ create().foo(); | ||
return new Promise(function(resolve) { | ||
var create = mixinable({ | ||
foo: mixinable.override, | ||
bar: mixinable.override, | ||
})({ | ||
foo: function() { | ||
t.pass('first method is being called'); | ||
setTimeout(this.bar, 5); | ||
var create = mixinable( | ||
{ | ||
foo: mixinable.override, | ||
bar: mixinable.override, | ||
}, | ||
bar: function() { | ||
t.pass('second method is being called'); | ||
setTimeout(this.baz, 5); | ||
}, | ||
baz: function() { | ||
t.pass('third method is being called'); | ||
t.truthy( | ||
this.constructor.prototype.baz.hasOwnProperty('prototype'), | ||
'third mixin prototype method is unbound' | ||
); | ||
t.falsy( | ||
this.baz.hasOwnProperty('prototype'), | ||
'third mixin method is bound' | ||
); | ||
setTimeout(this.qux, 5); | ||
}, | ||
qux: function() { | ||
t.pass('fourth method is being called'); | ||
t.truthy( | ||
this.constructor.prototype.qux.hasOwnProperty('prototype'), | ||
'fourth mixin prototype method is unbound' | ||
); | ||
t.falsy( | ||
this.qux.hasOwnProperty('prototype'), | ||
'fourth mixin method is bound' | ||
); | ||
resolve(); | ||
}, | ||
}); | ||
var instance = create(); | ||
instance.foo(); | ||
[ | ||
function() { | ||
Object.assign(this, { | ||
foo: function() { | ||
t.pass('first method is being called'); | ||
setTimeout(this.bar, 5); | ||
}, | ||
bar: function() { | ||
t.pass('second method is being called'); | ||
setTimeout(this.baz, 5); | ||
}, | ||
baz: function() { | ||
t.pass('third method is being called'); | ||
resolve(); | ||
}, | ||
}); | ||
}, | ||
] | ||
); | ||
create().foo(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
205268
790
295