revised tests + nodes and commens....

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-06-08 16:07:54 +03:00
parent 4167536a77
commit ca24b2ed54
3 changed files with 63 additions and 42 deletions

View File

@ -359,6 +359,11 @@ var Mixed = object.Constructor('Mixed', UtilityMixin(Base), {
var m = Mixed() var m = Mixed()
``` ```
**Notes:**
- It is not recommended to `.mixin(..)` into constructors directly, use
`.mixinFlat(..)` instead.
## Advanced usage ## Advanced usage
@ -664,6 +669,9 @@ keeping the prototype visibility the same.
This will copy the content of each input object without touching the This will copy the content of each input object without touching the
objects themselves, making them fully reusable. objects themselves, making them fully reusable.
It is not recommended to `.mixin(..)` into constructors directly, use
`.mixinFlat(..)` instead.
### `mixins(..)` ### `mixins(..)`

View File

@ -495,6 +495,18 @@ function(base, ...objects){
// //
// //
// NOTE: this will only mix in non-empty objects... // NOTE: this will only mix in non-empty objects...
// NOTE: mixing into a constructor will break object creation via new...
// Example:
// class A {}
// class B extends A {}
//
// mixin(B, {x: 123})
//
// var b = new B() // will break...
//
// This does not affect object.Constructor(..) chains...
// NOTE: mixin(Object.prototype, ..) will fail because Object.prototype.__proto__
// is imutable...
var mixin = var mixin =
module.mixin = module.mixin =
function(base, ...objects){ function(base, ...objects){

71
test.js
View File

@ -115,7 +115,8 @@ var instances = function(obj){
var makeAssert = function(pre, stats){ var makeAssert = function(pre, stats){
return function(e, msg, ...args){ return Object.assign(
function(e, msg, ...args){
stats stats
&& (stats.assertions += 1) && (stats.assertions += 1)
&& !e && !e
@ -123,7 +124,11 @@ var makeAssert = function(pre, stats){
module.VERBOSE module.VERBOSE
&& console.log(pre +': '+ msg.bold, ...args) && console.log(pre +': '+ msg.bold, ...args)
console.assert(e, pre.bold +': '+ msg.bold.yellow, ...args) console.assert(e, pre.bold +': '+ msg.bold.yellow, ...args)
return e } } return e },
{
// XXX should have a real path...
path: pre
}) }
@ -595,11 +600,18 @@ module.modifiers = {
: mode == 'raw' ? : mode == 'raw' ?
assert(O.__rawinstance__(), `.__rawinstance__()`, k) assert(O.__rawinstance__(), `.__rawinstance__()`, k)
: assert(new O(), `new:`, k) : assert(new O(), `new:`, k)
assert(o instanceof O, `instanceof:`, k) assert(o instanceof O, `instanceof:`, k)
O.__proto__ instanceof Function O.__proto__ instanceof Function
&& assert(o instanceof O.__proto__, `instanceof-nested:`, k) // XXX need to test this for constructor mixins too...
&& !(O.__mixin_constructors && !O.__mixin_flat)
&& assert(o instanceof o.constructor.__proto__, `instanceof-nested:`, k)
assert(o.constructor === O, `.constructor:`, k) assert(o.constructor === O, `.constructor:`, k)
assert(o.__proto__ === O.prototype, `.__proto__:`, k) assert(o.__proto__ === O.prototype, `.__proto__:`, k)
return res }, {}) }, return res }, {}) },
instance_no_new: function(assert, setup){ instance_no_new: function(assert, setup){
return this.instance(assert, setup, 'no_new') }, return this.instance(assert, setup, 'no_new') },
@ -616,17 +628,24 @@ module.modifiers = {
return res }, return res },
// mixins... // mixins...
mixin_instance: function(assert, setup, flat){ mixin_instance: function(assert, setup, flat, filter, get){
var mixin = setup.__mixin_instance = { filter = filter || instances
__mixin_instance: true, // XXX might be a good idea to get the method name from the context...
var attr = '__mixin_' + filter.name
var mixin = setup[attr] = {
[attr]: true,
__mixin_flat: !!flat,
// XXX // XXX
} }
mixin.__mixin_instance = mixin
instances(setup) mixin[attr] = mixin
filter(setup)
.forEach(function([n, o]){ .forEach(function([n, o]){
o = get ? get(o) : o
// mixin once per chain... // mixin once per chain...
if(o.__mixin_instance){ if(!o || o[attr]){
return } return }
assert(!object.hasMixin(o, mixin), 'pre mixin test', n) assert(!object.hasMixin(o, mixin), 'pre mixin test', n)
assert(flat ? assert(flat ?
@ -641,33 +660,15 @@ module.modifiers = {
mixin_instance_flat: function(assert, setup){ mixin_instance_flat: function(assert, setup){
return this.mixin_instance(assert, setup, true) }, return this.mixin_instance(assert, setup, true) },
mixin_constructor: function(assert, setup, flat){ mixin_constructor: function(assert, setup, flat){
var mixin = setup.__mixin_constructor = { return this.mixin_instance(assert, setup, false, constructors) },
__mixin_constructor: true, mixin_constructor_proto: function(assert, setup, flat){
return this.mixin_instance(assert, setup, false, constructors,
// XXX function(o){
} // skip mixing into Object.prototype...
mixin.__mixin_constructor = mixin return o !== Object
// XXX do we care about order??? && o.prototype }) },
constructors(setup)
.forEach(function([n, o]){
// special case: can't non-flat mixin into an Object...
if(!flat && o === Object){
return }
// mixin once per chain...
if(o.prototype.__mixin_constructor){
return }
assert(!object.hasMixin(o.prototype, mixin), 'pre mixin test', n)
assert(flat ?
object.mixinFlat(o.prototype, mixin)
: object.mixin(o.prototype, mixin),
flat ?
'mixin (flat)'
: 'mixin', n)
assert(object.hasMixin(o.prototype, mixin), 'mixin test', n)
})
return setup },
mixin_constructor_flat: function(assert, setup){ mixin_constructor_flat: function(assert, setup){
return this.mixin_constructor(assert, setup, true) }, return this.mixin_constructor_proto(assert, setup, true) },
/*/ XXX /*/ XXX
mixout: function(assert, setup){ mixout: function(assert, setup){
return {} return {}