removed legacy code...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-07-05 23:45:07 +03:00
parent 3b360bbf1c
commit 7cda40eb53
3 changed files with 74 additions and 166 deletions

216
object.js
View File

@ -378,12 +378,29 @@ BOOTSTRAP(function(){
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Prototype chain content access... // Prototype chain content access...
// XXX EXPEREMENTAL... // Get source objects for a prop/attr name...
// should we support multple names??? //
// XXX replace the current version with these... // sources(obj, name)
// ...this will lead to breaking API.. // -> iterator
var _sources = //
module._sources = // Get full chain...
// sources(obj)
// -> iterator
//
// Get callables or objects defining .__call__ (special-case)
// sources(obj, '__call__')
// -> iterator
//
//
// NOTE: this goes up the prototype chain, not caring about any role (
// instance/class or instance/prototype) bounderies and depends
// only on the object given as the starting point.
// It is possible to start the search from this, thus checking
// for any overloading in the instance, though this approach is
// not very reusable....
// NOTE: this will not trigger any props...
var sources =
module.sources =
function*(obj, name=undefined){ function*(obj, name=undefined){
while(obj != null){ while(obj != null){
if(name === undefined if(name === undefined
@ -393,11 +410,34 @@ function*(obj, name=undefined){
yield obj } yield obj }
obj = obj.__proto__ } } obj = obj.__proto__ } }
// XXX
var _entries = // Get object-value/prop pairs set in source objects for a prop/attr name...
module._entries = //
// entries(obj, name)
// -> iterator
//
// Get propery descriptors...
// entries(obj, name, true)
// -> iterator
//
//
// Item format:
// [
// object,
// value,
// ]
//
//
// Special case: name is given as '__call__'
// This will return either the value the object if it is callable
// or the value of .__call__ attribute...
//
//
// NOTE: for more docs see sources(..)
var entries =
module.entries =
function*(obj, name, props=false){ function*(obj, name, props=false){
for(var o of _sources(obj, name)){ for(var o of sources(obj, name)){
yield [ yield [
obj, obj,
props ? props ?
@ -410,155 +450,23 @@ function*(obj, name, props=false){
: obj[name], : obj[name],
] }} ] }}
// XXX
var _values =
module._values =
function*(obj, name, props=false){
for(var [_, value] of _entries(...arguments)){
yield value }}
// Get values/props set in source objects for a prop/attr name...
// Get a list of source objects for a prop/attr name...
// //
// sources(obj, name)
// sources(obj, name, callback)
// -> list
// -> []
//
// Get callables or objects defining .__call__ (special-case)
// sources(obj, '__call__')
// sources(obj, '__call__', callback)
// -> list
// -> []
//
// Get full chain...
// sources(obj)
// sources(obj, callback)
// -> list
//
//
// callback(obj, i)
// -> STOP
// -> STOP(value)
// -> ..
//
//
// The callback(..) is called with each matching object.
//
// callback(..) return values:
// - STOP - stop the search and return the match list terminated
// with the object triggering the stop.
// - STOP(value) - stop the search and return the match list terminated
// with the value passed to STOP(..)
// - undefined - return the triggering object as-is
// NOTE: this is the same as returning [obj]
// - array - merge array content into the result insteaad of
// the triggering value.
// NOTE: an ampty array will effectively omit the
// triggering object from the results.
// - other - return a value instead of the triggering object.
//
//
// NOTE: this goes up the prototype chain, not caring about any role (
// instance/class or instance/prototype) bounderies and depends
// only on the object given as the starting point.
// It is possible to start the search from this, thus checking
// for any overloading in the instance, though this approach is
// not very reusable....
// NOTE: this will not trigger any props...
var sources =
module.sources =
function(obj, name, callback){
// get full chain...
if(typeof(name) == 'function'){
callback = name
name = undefined }
var i = 0
var o
var res = []
while(obj != null){
//if(obj.hasOwnProperty(name)){
if(name === undefined
|| obj.hasOwnProperty(name)
|| (name == '__call__' && typeof(obj) == 'function')){
// handle callback...
o = callback
&& callback(obj, i++)
// manage results...
res.push(
(o === undefined || o === module.STOP) ?
[obj]
: o instanceof module.STOP ?
o.value
: o )
// stop...
if(o === module.STOP
|| o instanceof module.STOP){
return res.flat() } }
obj = obj.__proto__ }
return res.flat() }
// Get a list of values/props set in source objects for a prop/attr name...
//
// Get values...
// values(obj, name) // values(obj, name)
// values(obj, name, callback) // -> iterator
// -> list
// -> []
// //
// Get propery descriptors... // Get propery descriptors...
// values(obj, name, true) // values(obj, name, true)
// values(obj, name, callback, true) // -> iterator
// -> list
// -> []
//
// callback(value/prop, obj)
// -> STOP
// -> STOP(value)
// -> ..
// //
// //
// Special case: name is given as '__call__' // NOTE: this is specialization of entries(..), see that for more info.
// This will return either the value the object if it is callable
// or the value of .__call__ attribute...
//
//
// NOTE: for more docs on the callback(..) see sources(..)
var values = var values =
module.values = module.values =
function(obj, name, callback, props){ function*(obj, name, props=false){
props = callback === true ? for(var [_, value] of entries(...arguments)){
callback yield value }}
: props
var _get = function(obj, name){
return props ?
Object.getOwnPropertyDescriptor(obj, name)
// handle callable instance...
: !(name in obj)
&& name == '__call__'
&& typeof(obj) == 'function' ?
obj
// normal attr...
: obj[name] }
// wrap the callback if given...
var c = typeof(callback) == 'function'
&& function(obj, i){
var val = _get(obj, name)
var res = callback(val, obj, i)
return res === module.STOP ?
// wrap the expected stop result if the user did not do it...
module.STOP(val)
: res }
return c ?
// NOTE: we do not need to handle the callback return values as
// this is fully done by c(..) in sources(..)
sources(obj, name, c)
: sources(obj, name)
.map(function(obj){
return _get(obj, name) }) }
// Find the next parent attribute in the prototype chain. // Find the next parent attribute in the prototype chain.
@ -645,7 +553,7 @@ function(proto, name){
throw new Error('parent(..): need a method with non-empty .name') } throw new Error('parent(..): need a method with non-empty .name') }
// get first matching source... // get first matching source...
var i = 0 var i = 0
for(var obj of _sources(that, name)){ for(var obj of sources(that, name)){
// NOTE: the .hasOwnProperty(..) test is here so as // NOTE: the .hasOwnProperty(..) test is here so as
// to skip the base callable when searching for // to skip the base callable when searching for
// .__call__ that is returned as a special case // .__call__ that is returned as a special case
@ -657,7 +565,7 @@ function(proto, name){
proto = obj proto = obj
break }}} break }}}
// get first source... // get first source...
var res = _sources(proto, name) var res = sources(proto, name)
res.next() res.next()
res = res.next().value res = res.next().value
return !res ? return !res ?
@ -678,7 +586,7 @@ var parentProperty =
module.parentProperty = module.parentProperty =
function(proto, name){ function(proto, name){
// get second source... // get second source...
var res = _sources(proto, name) var res = sources(proto, name)
res.next() res.next()
res = res.next().value res = res.next().value
return res ? return res ?
@ -726,7 +634,7 @@ function(proto, name, that, ...args){
var parentOf = var parentOf =
module.parentOf = module.parentOf =
function(parent, child){ function(parent, child){
return new Set([..._sources(child)]).has(parent) } return new Set([...sources(child)]).has(parent) }
// Reverse of parentOf(..) // Reverse of parentOf(..)
var childOf = var childOf =
@ -1381,7 +1289,7 @@ function(base, object){
mixins(base, object, function(){ return module.STOP }) mixins(base, object, function(){ return module.STOP })
.length > 0 .length > 0
// flat mixin search... // flat mixin search...
|| [..._sources(base)] || [...sources(base)]
.some(function(p){ .some(function(p){
return matchPartial(p, object) }) )} return matchPartial(p, object) }) )}

View File

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

20
test.js
View File

@ -328,20 +328,20 @@ var setups = test.Setups({
method: function(){ method: function(){
var x, y var x, y
assert.array( assert.array(
[...object._values(c, 'x')], [...object.values(c, 'x')],
['c', 'a', 'b'], ['c', 'a', 'b'],
'reach all values of attr') 'reach all values of attr')
assert.array( assert.array(
[...object._values(c, 'x')] [...object.values(c, 'x')]
.map(function(v){ .map(function(v){
return v.toUpperCase() }), return v.toUpperCase() }),
['C', 'A', 'B'], ['C', 'A', 'B'],
'reach all values of attr') 'reach all values of attr')
assert.array( assert.array(
[...object._sources(c, 'method')], [...object.sources(c, 'method')],
// NOTE: not passing an explicit list as we need // NOTE: not passing an explicit list as we need
// to account for mixins... // to account for mixins...
[...object._sources(c)] [...object.sources(c)]
.filter(function(s){ .filter(function(s){
return s.hasOwnProperty('method') }), return s.hasOwnProperty('method') }),
'reach all values of method') 'reach all values of method')
@ -377,17 +377,17 @@ var setups = test.Setups({
method(){ method(){
// XXX this is almost the same as for js_prototype... // XXX this is almost the same as for js_prototype...
assert.array( assert.array(
[...object._values(c, 'x')], [...object.values(c, 'x')],
['z', 'y', 'x'], ['z', 'y', 'x'],
'reach all values of attr (class)') 'reach all values of attr (class)')
assert.array( assert.array(
[...object._values(c, 'x')] [...object.values(c, 'x')]
.map(function(v){ .map(function(v){
return v.toUpperCase() }), return v.toUpperCase() }),
['C', 'A', 'B'], ['C', 'A', 'B'],
'reach all values of attr (class)') 'reach all values of attr (class)')
assert.array( assert.array(
[...object._sources(c, 'method')], [...object.sources(c, 'method')],
[Z.prototype, X.prototype], [Z.prototype, X.prototype],
'reach all values of method (class)') 'reach all values of method (class)')
assert( assert(
@ -580,12 +580,12 @@ var tests = test.Tests({
var test = function(obj, name){ var test = function(obj, name){
var a, b var a, b
return assert(arrayCmp( return assert(arrayCmp(
a = [...object._values(obj, '__call__')] a = [...object.values(obj, '__call__')]
.map(function(func){ .map(function(func){
return func.call(obj) }) return func.call(obj) })
.flat(), .flat(),
// get all callables in prototype chain and call them... // get all callables in prototype chain and call them...
b = [...object._sources(obj)] b = [...object.sources(obj)]
.filter(function(o){ .filter(function(o){
return typeof(o) == 'function' return typeof(o) == 'function'
|| o.hasOwnProperty('__call__') }) || o.hasOwnProperty('__call__') })
@ -663,7 +663,7 @@ var cases = test.Cases({
obj.x = 321 obj.x = 321
assert.array( assert.array(
[...object._values(obj, 'x', true)] [...object.values(obj, 'x', true)]
.map(function(e){ return e.value }), .map(function(e){ return e.value }),
// XXX assert ignores the order here -- this should fail... // XXX assert ignores the order here -- this should fail...
[123, 321], '.values(.., true) ') [123, 321], '.values(.., true) ')