bugfix + added ability to pass value through STOP(..)

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-11-14 19:41:00 +03:00
parent 78529b667b
commit 17c970319a
4 changed files with 40 additions and 29 deletions

View File

@ -566,6 +566,7 @@ sources(<object>, <name>, <callback>)
```
callback(<source>)
-> STOP
-> STOP(<value>)
-> undefined
-> <value>
```
@ -576,6 +577,9 @@ one of the following:
- `object.STOP`
This will make `sources(..)` stop and return the `<list>` up to and
including the object that triggered the _stop_.
- `object.STOP(<value>)`
Same as returning `object.STOP` but will put the `<value>` at the end of
the returned list instead of the input object.
- `undefined`
Add the object triggering `callback(..)` in `<list>` as-is and continue.
- array
@ -625,6 +629,7 @@ values(<object>, <name>, <callback>, true)
```
callback(<descriptor>, <source>)
-> STOP
-> STOP(value)
-> undefined
-> <value>
```

View File

@ -248,8 +248,9 @@ function(base, obj, non_strict){
// object to trigger iteration stop...
//
module.STOP =
{doc: 'stop iteration.'}
// NOTE: this is a placeholder for documnetation/context purposes, see
// the actual implementation at the end of the module...
module.STOP = undefined
// Get a list of source objects for a prop/attr name...
@ -273,6 +274,7 @@ module.STOP =
//
// callback(obj)
// -> STOP
// -> STOP(value)
// -> ..
//
//
@ -281,6 +283,8 @@ module.STOP =
// 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
@ -319,9 +323,12 @@ function(obj, name, callback){
res.push(
(o === undefined || o === module.STOP) ?
[obj]
: o instanceof module.STOP ?
o.value
: o )
// stop...
if(o === module.STOP){
if(o === module.STOP
|| o instanceof module.STOP){
return res.flat() } }
obj = obj.__proto__ }
return res.flat() }
@ -343,6 +350,7 @@ function(obj, name, callback){
//
// callback(value/prop, obj)
// -> STOP
// -> STOP(value)
// -> ..
//
//
@ -352,20 +360,6 @@ function(obj, name, callback){
//
//
// NOTE: for more docs on the callback(..) see sources(..)
//
// XXX BUG: passing a callback here breaks the return value at the STOP...
// essentially this is a question of how can we return STOP and the
// value to be returned at the same time???
// ...ways to go:
// - store the last return from callback(..) and if it's STOP
// patch the last value (HACK-ish)
// - skip the last value...
// ...this will complicate the logic quite a bit as the user
// will need to STOP after the last position...
// - return STOP(value) or [STOP, value]
// ...requires the user not to forget...
// - ignore the callback return value...
// ...this seems the most uniform, but this can break things...
var values =
module.values =
function(obj, name, callback, props){
@ -385,11 +379,15 @@ function(obj, name, callback, props){
// wrap the callback if given...
var c = typeof(callback) == 'function'
&& function(obj){
return callback(_get(obj, name), obj) }
var val = _get(obj, name)
var res = callback(val, obj)
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(..)
// XXX BUG: if this stops the last value will be the obj and not the prop...
sources(obj, name, c)
: sources(obj, name)
.map(function(obj){
@ -668,8 +666,11 @@ function(base, object, callback){
res.push(
(o === undefined || o === module.STOP) ?
[base]
: o instanceof module.STOP ?
o.value
: o )
if(o === module.STOP){
if(o === module.STOP
|| o instanceof module.STOP){
return res.flat() }
// match found, no need to test further...
break } }
@ -1129,6 +1130,16 @@ function Constructor(name, a, b, c){
//---------------------------------------------------------------------
//
module.STOP = Constructor('STOP', {
doc: 'stop iteration.',
__init__: function(value){
this.value = value },
})
/**********************************************************************
* vim:set ts=4 sw=4 : */ return module })

View File

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

View File

@ -662,11 +662,6 @@ var cases = test.Cases({
// XXX essert ignores the order here -- this should fail...
[123, 321], '.values(.., true) ')
// XXX BUG: this returns the object and not the value...
console.log('>>>>>', object.values(obj, 'x', function(){ return object.STOP }))
// XXX BUG: this returns the object and not the prop descriptor...
console.log('>>>>>', object.values(obj, 'x', function(){ return object.STOP }, true))
assert(
object.values(obj, 'x', function(){ return object.STOP })[0] == 321,
// XXX essert ignores the order here -- this should fail...