mirror of
https://github.com/flynx/object.js.git
synced 2025-10-28 18:10:08 +00:00
moved code to ig-stoppable...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
dcb1321e6a
commit
6d85d8718c
132
object.js
132
object.js
@ -21,6 +21,12 @@
|
||||
(function(require){ var module={} // make module AMD/node compatible...
|
||||
/*********************************************************************/
|
||||
|
||||
var STOP =
|
||||
module.STOP =
|
||||
require('ig-stoppable').STOP
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// Function methods to link into a constructor producing a callable
|
||||
// defined via .__call__(..)
|
||||
@ -344,18 +350,6 @@ function(obj){
|
||||
//---------------------------------------------------------------------
|
||||
// Helper objects/constructors...
|
||||
|
||||
// NOTE: these are missing from JavaScript for some reason...
|
||||
//
|
||||
// XXX should these be global???
|
||||
var Generator =
|
||||
module.Generator =
|
||||
(function*(){}).constructor
|
||||
|
||||
var AsyncGenerator =
|
||||
module.AsyncGenerator =
|
||||
(async function*(){}).constructor
|
||||
|
||||
|
||||
BOOTSTRAP(function(){
|
||||
|
||||
// Error with some JS quirks fixed...
|
||||
@ -377,119 +371,9 @@ BOOTSTRAP(function(){
|
||||
//return Reflect.construct(Error, args, this.constructor) },
|
||||
})
|
||||
|
||||
|
||||
// Value trigger iteration stop and to carry results...
|
||||
//
|
||||
module.STOP =
|
||||
Constructor('STOP', {
|
||||
doc: 'stop iteration.',
|
||||
__init__: function(value){
|
||||
this.value = value },
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
// Wrap a callable in a STOP handler
|
||||
//
|
||||
// stoppable(func)
|
||||
// -> func
|
||||
//
|
||||
// stoppable(gen)
|
||||
// -> gen
|
||||
//
|
||||
// stoppable(asyncgen)
|
||||
// -> asyncgen
|
||||
//
|
||||
//
|
||||
// The client callable can be one of:
|
||||
// - function
|
||||
// - generator
|
||||
// - async generator
|
||||
//
|
||||
// The returned callable will be of the same type as the input callable.
|
||||
//
|
||||
// The wrapper handles STOP slightly differently if the client is a
|
||||
// function or if it is a generator / async generator:
|
||||
// - function
|
||||
// STOP returned / thrown
|
||||
// -> return undefined
|
||||
// STOP(value) returned / thrown
|
||||
// -> return value
|
||||
// - generator / async generator
|
||||
// STOP yielded / thrown
|
||||
// -> iteration stops
|
||||
// STOP(value) yielded / thrown
|
||||
// -> value yielded and iteration stops
|
||||
//
|
||||
//
|
||||
// NOTE: this repeats the same code at lest twice, not sure yet how to avoid
|
||||
// this...
|
||||
//
|
||||
// XXX user doc!!!
|
||||
var stoppable =
|
||||
module.stoppable =
|
||||
function(func){
|
||||
return Object.assign(
|
||||
func instanceof Generator ?
|
||||
// NOTE: the only difference between Generator/AsyncGenerator
|
||||
// versions of this is the async keyword -- keep them
|
||||
// in sync...
|
||||
function*(){
|
||||
try{
|
||||
for(var res of func.call(this, ...arguments)){
|
||||
if(res === STOP){
|
||||
return }
|
||||
if(res instanceof STOP){
|
||||
yield res.value
|
||||
return }
|
||||
yield res }
|
||||
} catch(err){
|
||||
if(err === STOP){
|
||||
return
|
||||
} else if(err instanceof STOP){
|
||||
yield err.value
|
||||
return }
|
||||
throw err } }
|
||||
: func instanceof AsyncGenerator ?
|
||||
// NOTE: the only difference between Generator/AsyncGenerator
|
||||
// versions of this is the async keyword -- keep them
|
||||
// in sync...
|
||||
async function*(){
|
||||
try{
|
||||
for(var res of func.call(this, ...arguments)){
|
||||
if(res === STOP){
|
||||
return }
|
||||
if(res instanceof STOP){
|
||||
yield res.value
|
||||
return }
|
||||
yield res }
|
||||
} catch(err){
|
||||
if(err === STOP){
|
||||
return
|
||||
} else if(err instanceof STOP){
|
||||
yield err.value
|
||||
return }
|
||||
throw err } }
|
||||
: function(){
|
||||
try{
|
||||
var res = func.call(this, ...arguments)
|
||||
// NOTE: this is here for uniformity...
|
||||
if(res === STOP){
|
||||
return }
|
||||
if(res instanceof STOP){
|
||||
return res.value }
|
||||
return res
|
||||
} catch(err){
|
||||
if(err === STOP){
|
||||
return
|
||||
} else if(err instanceof STOP){
|
||||
return err.value }
|
||||
throw err } },
|
||||
{ toString: function(){
|
||||
return func.toString() }, }) }
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Prototype chain content access...
|
||||
@ -523,7 +407,7 @@ function*(obj, name, props=false){
|
||||
&& name == '__call__'
|
||||
&& typeof(obj) == 'function' ?
|
||||
obj
|
||||
: obj[name]
|
||||
: obj[name],
|
||||
] }}
|
||||
|
||||
// XXX
|
||||
@ -1448,6 +1332,8 @@ function(base, ...objects){
|
||||
// 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(..)
|
||||
//
|
||||
// XXX should this be a generator???
|
||||
var mixins =
|
||||
module.mixins =
|
||||
function(base, object, callback){
|
||||
|
||||
@ -28,5 +28,8 @@
|
||||
"c8": "^7.3.5",
|
||||
"colors": "1.4.0",
|
||||
"ig-test": "^1.4.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"ig-stoppable": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
32
test.js
32
test.js
@ -328,21 +328,22 @@ var setups = test.Setups({
|
||||
method: function(){
|
||||
var x, y
|
||||
assert.array(
|
||||
object.values(c, 'x'),
|
||||
[...object._values(c, 'x')],
|
||||
['c', 'a', 'b'],
|
||||
'reach all values of attr')
|
||||
assert.array(
|
||||
object.values(c, 'x', function(v, o){
|
||||
return v.toUpperCase() }),
|
||||
[...object._values(c, 'x')]
|
||||
.map(function(v){
|
||||
return v.toUpperCase() }),
|
||||
['C', 'A', 'B'],
|
||||
'reach all values of attr')
|
||||
assert.array(
|
||||
object.sources(c, 'method'),
|
||||
[...object._sources(c, 'method')],
|
||||
// NOTE: not passing an explicit list as we need
|
||||
// to account for mixins...
|
||||
object.sources(c)
|
||||
.filter(function(s){
|
||||
return s.hasOwnProperty('method') }),
|
||||
[...object._sources(c)]
|
||||
.filter(function(s){
|
||||
return s.hasOwnProperty('method') }),
|
||||
'reach all values of method')
|
||||
assert(
|
||||
(x = object.parent(c, 'x')) == 'b',
|
||||
@ -376,16 +377,17 @@ var setups = test.Setups({
|
||||
method(){
|
||||
// XXX this is almost the same as for js_prototype...
|
||||
assert.array(
|
||||
object.values(c, 'x'),
|
||||
[...object._values(c, 'x')],
|
||||
['z', 'y', 'x'],
|
||||
'reach all values of attr (class)')
|
||||
assert.array(
|
||||
object.values(c, 'x', function(v, o){
|
||||
return v.toUpperCase() }),
|
||||
[...object._values(c, 'x')]
|
||||
.map(function(v){
|
||||
return v.toUpperCase() }),
|
||||
['C', 'A', 'B'],
|
||||
'reach all values of attr (class)')
|
||||
assert.array(
|
||||
object.sources(c, 'method'),
|
||||
[...object._sources(c, 'method')],
|
||||
[Z.prototype, X.prototype],
|
||||
'reach all values of method (class)')
|
||||
assert(
|
||||
@ -578,12 +580,12 @@ var tests = test.Tests({
|
||||
var test = function(obj, name){
|
||||
var a, b
|
||||
return assert(arrayCmp(
|
||||
a = object.values(obj, '__call__')
|
||||
a = [...object._values(obj, '__call__')]
|
||||
.map(function(func){
|
||||
return func.call(obj) })
|
||||
.flat(),
|
||||
// get all callables in prototype chain and call them...
|
||||
b = object.sources(obj)
|
||||
b = [...object._sources(obj)]
|
||||
.filter(function(o){
|
||||
return typeof(o) == 'function'
|
||||
|| o.hasOwnProperty('__call__') })
|
||||
@ -661,11 +663,12 @@ var cases = test.Cases({
|
||||
obj.x = 321
|
||||
|
||||
assert.array(
|
||||
object.values(obj, 'x', true)
|
||||
[...object._values(obj, 'x', true)]
|
||||
.map(function(e){ return e.value }),
|
||||
// XXX assert ignores the order here -- this should fail...
|
||||
[123, 321], '.values(.., true) ')
|
||||
|
||||
/* XXX GENERATOR not relevant...
|
||||
assert(
|
||||
object.values(obj, 'x', function(){ return object.STOP })[0] == 321,
|
||||
// XXX assert ignores the order here -- this should fail...
|
||||
@ -678,6 +681,7 @@ var cases = test.Cases({
|
||||
object.values(obj, 'x', function(){ return object.STOP(555) }, true)[0] == 555,
|
||||
// XXX assert ignores the order here -- this should fail...
|
||||
'.values(.., func, true) with explicit stop value')
|
||||
//*/
|
||||
|
||||
},
|
||||
deepKeys: function(assert){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user