mirror of
https://github.com/flynx/object.js.git
synced 2025-10-29 10:30: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.
|
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
|
## Limitations
|
||||||
|
|
||||||
### Can not mix unrelated native types
|
### Can not mix unrelated native types
|
||||||
|
|||||||
31
object.js
31
object.js
@ -151,6 +151,20 @@ function(base, obj, non_strict){
|
|||||||
return true }
|
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...
|
// Prototype chain content access...
|
||||||
@ -502,8 +516,8 @@ function(base, ...objects){
|
|||||||
// -> undefined
|
// -> undefined
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// NOTE: if base matches directly callback(..) will get undefined as parent
|
|
||||||
// NOTE: this will also match base...
|
// 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(..)
|
// NOTE: for more docs on the callback(..) see sources(..)
|
||||||
var mixins =
|
var mixins =
|
||||||
module.mixins =
|
module.mixins =
|
||||||
@ -540,10 +554,20 @@ function(base, object, callback){
|
|||||||
// -> bool
|
// -> bool
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
// NOTE: to test for a flat mixin directly use .matchPartial(base, object)
|
||||||
var hasMixin =
|
var hasMixin =
|
||||||
module.hasMixin =
|
module.hasMixin =
|
||||||
function(base, object){
|
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...
|
// Mix-out sets of methods/props/attrs out of an object prototype chain...
|
||||||
@ -886,7 +910,8 @@ function Constructor(name, a, b, c){
|
|||||||
!!constructor_proto
|
!!constructor_proto
|
||||||
&& (proto.__proto__ = constructor_proto.prototype) }
|
&& (proto.__proto__ = constructor_proto.prototype) }
|
||||||
|
|
||||||
// the constructor base...
|
// the constructor base...
|
||||||
|
/* c8 ignore next 9 */
|
||||||
var _constructor = function Constructor(){
|
var _constructor = function Constructor(){
|
||||||
// create raw instance...
|
// create raw instance...
|
||||||
var obj = _constructor.__rawinstance__ ?
|
var obj = _constructor.__rawinstance__ ?
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ig-object",
|
"name": "ig-object",
|
||||||
"version": "5.0.7",
|
"version": "5.0.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "object.js",
|
"main": "object.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
72
test.js
72
test.js
@ -101,14 +101,16 @@ var arrayCmp = function(a, b){
|
|||||||
var constructors = function(obj){
|
var constructors = function(obj){
|
||||||
return Object.entries(obj)
|
return Object.entries(obj)
|
||||||
.filter(function([k, o]){
|
.filter(function([k, o]){
|
||||||
return k[0] == k[0].toUpperCase()
|
return !k.startsWith('_')
|
||||||
|
&& k[0] == k[0].toUpperCase()
|
||||||
&& o.prototype }) }
|
&& o.prototype }) }
|
||||||
|
|
||||||
// an instance is a thing that starts with a lowercase and has a .constructor
|
// an instance is a thing that starts with a lowercase and has a .constructor
|
||||||
var instances = function(obj){
|
var instances = function(obj){
|
||||||
return Object.entries(obj)
|
return Object.entries(obj)
|
||||||
.filter(function([k, o]){
|
.filter(function([k, o]){
|
||||||
return k[0] == k[0].toLowerCase()
|
return !k.startsWith('_')
|
||||||
|
&& k[0] == k[0].toLowerCase()
|
||||||
&& o.constructor }) }
|
&& o.constructor }) }
|
||||||
|
|
||||||
|
|
||||||
@ -319,6 +321,7 @@ var ArgvParser = function(spec){
|
|||||||
var setups =
|
var setups =
|
||||||
module.setups = {
|
module.setups = {
|
||||||
// basic constructor and inheritance...
|
// basic constructor and inheritance...
|
||||||
|
// XXX constructor methods...
|
||||||
basic: function(assert){
|
basic: function(assert){
|
||||||
var X, Y, A, B, C
|
var X, Y, A, B, C
|
||||||
return {
|
return {
|
||||||
@ -326,10 +329,12 @@ module.setups = {
|
|||||||
Y: Y = assert(object.C('Y', { }), `C`),
|
Y: Y = assert(object.C('Y', { }), `C`),
|
||||||
|
|
||||||
A: A = assert(object.C('A', Y, { }), `inherit (gen1)`),
|
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)`),
|
C: C = assert(object.C('C', B, { }), `inherit (gen3)`),
|
||||||
} },
|
} },
|
||||||
|
|
||||||
|
// XXX constructor methods...
|
||||||
|
|
||||||
// initialization...
|
// initialization...
|
||||||
init: function(assert){
|
init: function(assert){
|
||||||
var A, B, C
|
var A, B, C
|
||||||
@ -377,6 +382,9 @@ module.setups = {
|
|||||||
B: B = assert(object.C('B', {
|
B: B = assert(object.C('B', {
|
||||||
__non_function: true,
|
__non_function: true,
|
||||||
__call__: function(){
|
__call__: function(){
|
||||||
|
assert(
|
||||||
|
object.parentCall(B.prototype, '__call__', this, ...arguments) === undefined,
|
||||||
|
'call non-existent parent method', 'B')
|
||||||
return 'B'
|
return 'B'
|
||||||
},
|
},
|
||||||
}), 'callable'),
|
}), 'callable'),
|
||||||
@ -590,6 +598,64 @@ module.modifiers = {
|
|||||||
{__created_raw: true}) })
|
{__created_raw: true}) })
|
||||||
return res },
|
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...
|
// sanity checks...
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user