mirror of
https://github.com/flynx/object.js.git
synced 2025-10-29 18:40:08 +00:00
added .matchPartial(..) and reworked .hasMixin(..) + testing...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
26e3d8a825
commit
ff9d79a6a5
16
README.md
16
README.md
@ -854,6 +854,22 @@ Like the default case but uses _equality_ instead of _identity_ to match
|
||||
values.
|
||||
|
||||
|
||||
### `matchPartial(..)`
|
||||
|
||||
```
|
||||
match(base, obj)
|
||||
-> bool
|
||||
|
||||
// non-strict version...
|
||||
match(base, obj, true)
|
||||
-> bool
|
||||
```
|
||||
|
||||
Like `.match(..)` but will check for a partial match, i.e. when `obj` is
|
||||
a non-strict subset of `base`.
|
||||
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
### Can not mix unrelated native types
|
||||
|
||||
29
object.js
29
object.js
@ -151,6 +151,20 @@ function(base, obj, non_strict){
|
||||
return true }
|
||||
|
||||
|
||||
// Like .match(..) but will test if obj's attributes are included in base
|
||||
var matchPartial =
|
||||
module.matchPartial =
|
||||
function(base, obj, non_strict){
|
||||
return base === obj
|
||||
|| Object.entries(obj)
|
||||
.filter(function([n, v]){
|
||||
return !base.hasOwnProperty(n)
|
||||
|| (non_strict ?
|
||||
base[n] != v
|
||||
: base[n] !== v) })
|
||||
.length == 0 }
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Prototype chain content access...
|
||||
@ -502,8 +516,8 @@ function(base, ...objects){
|
||||
// -> undefined
|
||||
//
|
||||
//
|
||||
// NOTE: if base matches directly callback(..) will get undefined as parent
|
||||
// NOTE: this will also match base...
|
||||
// NOTE: if base matches directly callback(..) will get undefined as parent
|
||||
// NOTE: for more docs on the callback(..) see sources(..)
|
||||
var mixins =
|
||||
module.mixins =
|
||||
@ -540,10 +554,20 @@ function(base, object, callback){
|
||||
// -> bool
|
||||
//
|
||||
//
|
||||
// NOTE: to test for a flat mixin directly use .matchPartial(base, object)
|
||||
var hasMixin =
|
||||
module.hasMixin =
|
||||
function(base, object){
|
||||
return mixins(base, object, function(){ return module.STOP }).length > 0 }
|
||||
return (
|
||||
// normal mixin...
|
||||
mixins(base, object, function(){ return module.STOP })
|
||||
.length > 0
|
||||
// flat mixin search...
|
||||
|| sources(base, function(p){
|
||||
return matchPartial(p, object) ?
|
||||
module.STOP
|
||||
: [] })
|
||||
.length > 0 )}
|
||||
|
||||
|
||||
// Mix-out sets of methods/props/attrs out of an object prototype chain...
|
||||
@ -887,6 +911,7 @@ function Constructor(name, a, b, c){
|
||||
&& (proto.__proto__ = constructor_proto.prototype) }
|
||||
|
||||
// the constructor base...
|
||||
/* c8 ignore next 9 */
|
||||
var _constructor = function Constructor(){
|
||||
// create raw instance...
|
||||
var obj = _constructor.__rawinstance__ ?
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ig-object",
|
||||
"version": "5.0.7",
|
||||
"version": "5.0.8",
|
||||
"description": "",
|
||||
"main": "object.js",
|
||||
"scripts": {
|
||||
|
||||
72
test.js
72
test.js
@ -101,14 +101,16 @@ var arrayCmp = function(a, b){
|
||||
var constructors = function(obj){
|
||||
return Object.entries(obj)
|
||||
.filter(function([k, o]){
|
||||
return k[0] == k[0].toUpperCase()
|
||||
return !k.startsWith('_')
|
||||
&& k[0] == k[0].toUpperCase()
|
||||
&& o.prototype }) }
|
||||
|
||||
// an instance is a thing that starts with a lowercase and has a .constructor
|
||||
var instances = function(obj){
|
||||
return Object.entries(obj)
|
||||
.filter(function([k, o]){
|
||||
return k[0] == k[0].toLowerCase()
|
||||
return !k.startsWith('_')
|
||||
&& k[0] == k[0].toLowerCase()
|
||||
&& o.constructor }) }
|
||||
|
||||
|
||||
@ -319,6 +321,7 @@ var ArgvParser = function(spec){
|
||||
var setups =
|
||||
module.setups = {
|
||||
// basic constructor and inheritance...
|
||||
// XXX constructor methods...
|
||||
basic: function(assert){
|
||||
var X, Y, A, B, C
|
||||
return {
|
||||
@ -326,10 +329,12 @@ module.setups = {
|
||||
Y: Y = assert(object.C('Y', { }), `C`),
|
||||
|
||||
A: A = assert(object.C('A', Y, { }), `inherit (gen1)`),
|
||||
B: B = assert(object.C('B', A, { }), `inherit (gen2)`),
|
||||
B: B = assert(object.C('B', A, { }, { }), `inherit (gen2)`),
|
||||
C: C = assert(object.C('C', B, { }), `inherit (gen3)`),
|
||||
} },
|
||||
|
||||
// XXX constructor methods...
|
||||
|
||||
// initialization...
|
||||
init: function(assert){
|
||||
var A, B, C
|
||||
@ -377,6 +382,9 @@ module.setups = {
|
||||
B: B = assert(object.C('B', {
|
||||
__non_function: true,
|
||||
__call__: function(){
|
||||
assert(
|
||||
object.parentCall(B.prototype, '__call__', this, ...arguments) === undefined,
|
||||
'call non-existent parent method', 'B')
|
||||
return 'B'
|
||||
},
|
||||
}), 'callable'),
|
||||
@ -590,6 +598,64 @@ module.modifiers = {
|
||||
{__created_raw: true}) })
|
||||
return res },
|
||||
|
||||
// mixins...
|
||||
mixin_instance: function(assert, setup, flat){
|
||||
var mixin = setup.__mixin_instance = {
|
||||
__mixin_instance: true,
|
||||
|
||||
// XXX
|
||||
}
|
||||
mixin.__mixin_instance = mixin
|
||||
instances(setup)
|
||||
.forEach(function([n, o]){
|
||||
// mixin once per chain...
|
||||
if(o.__mixin_instance){
|
||||
return }
|
||||
assert(!object.hasMixin(o, mixin), 'pre mixin test', n)
|
||||
assert(flat ?
|
||||
object.mixinFlat(o, mixin)
|
||||
: object.mixin(o, mixin),
|
||||
flat ?
|
||||
'mixin (flat)'
|
||||
:'mixin', n)
|
||||
assert(object.hasMixin(o, mixin), 'mixin test', n)
|
||||
})
|
||||
return setup },
|
||||
mixin_instance_flat: function(assert, setup){
|
||||
return this.mixin_instance(assert, setup, true) },
|
||||
mixin_constructor: function(assert, setup, flat){
|
||||
var mixin = setup.__mixin_constructor = {
|
||||
__mixin_constructor: true,
|
||||
|
||||
// XXX
|
||||
}
|
||||
mixin.__mixin_constructor = mixin
|
||||
// XXX do we care about order???
|
||||
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){
|
||||
return this.mixin_constructor(assert, setup, true) },
|
||||
/*/ XXX
|
||||
mixout: function(assert, setup){
|
||||
return {}
|
||||
},
|
||||
//*/
|
||||
|
||||
// sanity checks...
|
||||
//
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user