updated docs, tests and notes..

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-06-01 02:49:00 +03:00
parent 17a4104514
commit b4ceef5c93
4 changed files with 100 additions and 36 deletions

View File

@ -373,6 +373,13 @@ var LowLevel = object.Constructor('LowLevel', {
```
The value `.__new__(..)` returns is used as the instance and gets linked
to the prototype chain by the calling constructor's `.__rawinstance__(..)`,
the constructor then will call `.__init__(..)` if defined.
_Note that `.__init__(..)` is called by the constructor and not by
`RawInstance(..)` or `.__rawinstance__(..)`._
Like [_function constructor_ and `.__call__(..)`](#callable-instances)
this also has two contexts, but the internal context is different -- as
it is the job of `.__new__(..)` to create an instance, at time of call
@ -389,10 +396,6 @@ Contexts:
(`window` or `global` by default), the same as for function constructor
and `.__call__(..)`.
The value `.__new__(..)`returns is used as the instance and gets linked
in the prototype chain.
This has priority over the callable protocols above, thus the user must
take care of both the _function constructor_ and `prototype.__call__(..)`
handling.

View File

@ -115,6 +115,8 @@ function(text, tab_size, keep_tabs){
// - attr names are the same and,
// - attr values are identical.
//
// NOTE: this will do a shallow test using Object.keys(..) thus .__proto__
// attributes are ignored...
var match =
module.match =
function(base, obj){

View File

@ -1,6 +1,6 @@
{
"name": "ig-object",
"version": "5.0.2",
"version": "5.0.3",
"description": "",
"main": "object.js",
"scripts": {

121
test.js
View File

@ -30,6 +30,13 @@ module.VERBOSE = process ?
//---------------------------------------------------------------------
// helpers...
var deepKeys = function(obj, stop){
var res = []
while(obj !== stop && obj != null){
res.push(Object.keys(obj))
obj = obj.__proto__ }
return [...(new Set(res.flat()))] }
// a constructor is a thing that starts with a capital and has a .prototype
var constructors = function(obj){
return Object.entries(obj)
@ -75,8 +82,38 @@ var setups = {
// initialization...
init: function(assert){
var A, B, C
return {
// init...
A: A = assert(object.C('A', {
msg: '.__init__()',
__init__: function(){
this.init_has_run = true },
test_init: function(){
this.__created_raw ?
assert(!this.init_has_run, this.msg+' did not run')
: assert(this.init_has_run, this.msg+' run') },
}), 'basic .__init__(..)'),
// new...
B: B = assert(object.C('B', {
__new__: function(){
var o = {}
o.new_has_run = true
return o
},
test_new: function(){
assert(this.new_has_run, '.__new__() run') },
}), 'basic .__new__(..)'),
// new + init...
C: C = assert(object.C('C', B, {
msg: '.__init__() after .__new__()',
__init__: function(){
this.init_has_run = true },
test_init: A.prototype.test_init,
}), `inherit .__new__()`),
// XXX gen2 and extended stuff???
// XXX
} },
// callable instances...
@ -89,6 +126,7 @@ var setups = {
return 'A'
}), 'callable'),
B: B = assert(object.C('B', {
__non_function: true,
__call__: function(){
return 'B'
},
@ -161,55 +199,79 @@ var modifiers = {
res[n+'g'+gen] = object.C(n+'g'+gen, O, {})
return res }, {}) },
gen3: function(assert, setup){
return this.gen2(assert, this.gen2(assert, setup), '3') }
return this.gen2(assert, this.gen2(assert, setup), '3') },
// XXX
// generate instances...
// NOTE: these are re-used as tests too...
instance: function(assert, setup, mode){
return constructors(setup)
.reduce(function(res, [k, O]){
var o = res[k.toLowerCase()] =
mode == 'no_new' ?
assert(O(), `new:`, k)
: mode == 'raw' ?
assert(O.__rawinstance__(), `.__rawinstance__()`, k)
: assert(new O(), `new:`, k)
assert(o instanceof O, `instanceof:`, k)
O.__proto__ instanceof Function
&& assert(o instanceof O.__proto__, `instanceof-nested:`, k)
assert(o.constructor === O, `.constructor:`, k)
assert(o.__proto__ === O.prototype, `.__proto__:`, k)
return res }, {}) },
instance_no_new: function(assert, setup){
return this.instance(assert, setup, 'no_new') },
// NOTE: here we mark the raw instances with .__created_raw
instance_raw: function(assert, setup){
var res = this.instance(assert, setup, 'raw')
Object.values(res)
.forEach(function(e){
Object.assign(
e,
{__created_raw: true}) })
return res },
}
var tests = {
// instance creation...
instance: function(assert, setup, mode){
return constructors(setup)
.reduce(function(res, [k, O]){
var o = res[k.toLowerCase()] =
mode == 'no_new' ?
assert(O(), `new:`, k)
: mode == 'raw' ?
assert(O.__rawinstance__(), `.__rawinstance__()`, k)
: assert(new O(), `new:`, k)
assert(o instanceof O, `instanceof:`, k)
O.__proto__ instanceof Function
&& assert(o instanceof O.__proto__, `instanceof-nested:`, k)
assert(o.constructor === O, `.constructor:`, k)
assert(o.__proto__ === O.prototype, `.__proto__:`, k)
return res }, {}) },
instance_no_new: function(assert, setup){
return this.instance(assert, setup, 'no_new') },
instance_raw: function(assert, setup){
return this.instance(assert, setup, 'raw') },
instance: modifiers.instance,
instance_no_new: modifiers.instance_no_new,
instance_raw: modifiers.instance_raw,
/*/ XXX
attributes: function(assert, setup){
return {} },
//*/
// XXX
methods: function(assert, setup){
instances(setup)
.forEach(function([k, o]){
deepKeys(o)
.forEach(function(m){
typeof(o[m]) == 'function'
// skip special methods...
&& !m.startsWith('__')
&& o[m]() }) })
return {} },
constructor_methods: function(assert, setup){
constructors(setup)
.forEach(function([k, O]){
Object.keys(O).forEach(function(m){
typeof(O[m]) == 'function'
&& O[m]() })
})
deepKeys(O)
.forEach(function(m){
typeof(O[m]) == 'function'
// skip special methods...
&& !m.startsWith('__')
&& O[m]() }) })
return {} },
callables: function(assert, setup){
return instances(setup)
.map(function([k, o]){
// NOTE: not all callables are instances of Function...
//assert(typeof(o) == 'function'
// && o instanceof Function, 'instanceof Function', k)
typeof(o) == 'function'
&& (o.__non_function ?
assert(!(o instanceof Function), 'non-instanceof Function', k)
: assert(o instanceof Function, 'instanceof Function', k))
return typeof(o) == 'function'
&& assert(o(), 'call', k) }) },
}
@ -245,7 +307,6 @@ var runner = function(){
assertions: 0,
failures: 0,
}
// tests...
Object.keys(tests)
.forEach(function(t){
@ -268,12 +329,10 @@ var runner = function(){
.forEach(function(c){
stats.tests += 1
cases[c]( makeAssert(`case:${c}:`, stats) ) })
// stats...
console.log('Tests run:', stats.tests,
'Assertions:', stats.assertions,
'Failures:', stats.failures)
return stats }