| 
									
										
										
										
											2020-11-02 18:24:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************/  /* c8 ignore next 2 */ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var object = require('ig-object') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 18:24:20 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | var IterablePromise = | 
					
						
							|  |  |  | module.IterablePromise = | 
					
						
							|  |  |  | object.Constructor('IterablePromise', Promise, { | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	[
 | 
					
						
							|  |  |  | 	//		[ <value> ],
 | 
					
						
							|  |  |  | 	//		<promise>,
 | 
					
						
							|  |  |  | 	//		...
 | 
					
						
							|  |  |  | 	// 	]
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	__list: null, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	// iterator methods...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// These will return a new IterablePromise instance...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	// When called from a resolved promise these will return a new 
 | 
					
						
							|  |  |  | 	// resolved promise with updated values...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// When called from a rejected promise these will return a rejected 
 | 
					
						
							|  |  |  | 	// with the same reason promise...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	// NOTE: these are different to Array's equivalents in that the handler
 | 
					
						
							|  |  |  | 	// 		is called not in the order of the elements but rather in order 
 | 
					
						
							|  |  |  | 	// 		of promise resolution...
 | 
					
						
							|  |  |  | 	// NOTE: index of items is unknowable because items can expand on 
 | 
					
						
							|  |  |  | 	// 		contract depending on handlrs (e.g. .filter(..) can remove 
 | 
					
						
							|  |  |  | 	// 		items)...
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	// 		This the following can not be implemented here:
 | 
					
						
							|  |  |  | 	// 			.slice(..)
 | 
					
						
							|  |  |  | 	// 			.splice(..)
 | 
					
						
							|  |  |  | 	// 			.at(..)
 | 
					
						
							|  |  |  | 	// 			[Symbol.iterator]()		- needs to be sync...
 | 
					
						
							|  |  |  | 	// 		The followng methods are questionable:
 | 
					
						
							|  |  |  | 	// 			.indexOf(..)
 | 
					
						
							|  |  |  | 	// 			.includes(..)
 | 
					
						
							|  |  |  | 	// 			.some(..) / .every(..)
 | 
					
						
							|  |  |  | 	// 			.sort(..)
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	map: function(func){ | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 		return this.constructor(this.__list, function(e){ | 
					
						
							|  |  |  | 			return [func(e)] }) }, | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	filter: function(func){ | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 		return this.constructor(this.__list, function(e){ | 
					
						
							|  |  |  | 			return func(e) ?  | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 				[e]  | 
					
						
							|  |  |  | 				: [] }) }, | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 	reduce: function(func, res){ | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 		return this.constructor(this.__list,  | 
					
						
							|  |  |  | 			function(e){ | 
					
						
							|  |  |  | 				res = func(res, e) | 
					
						
							|  |  |  | 				return [] }) | 
					
						
							|  |  |  | 			.then(function(){  | 
					
						
							|  |  |  | 				return res }) }, | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 	flat: function(depth=1){ | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 		return this.constructor(this.__list, function(e){  | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 			return (e && e.flat) ?  | 
					
						
							|  |  |  | 				e.flat(depth)  | 
					
						
							|  |  |  | 				: e }) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	// XXX do we need:
 | 
					
						
							|  |  |  | 	// 			.pop()
 | 
					
						
							|  |  |  | 	// 			.shift()
 | 
					
						
							|  |  |  | 	// 			.first() / .last()
 | 
					
						
							|  |  |  | 	// XXX these can change the "resolved" state...
 | 
					
						
							|  |  |  | 	// 		...i.e. return a pending promise when called from a fulfilled 
 | 
					
						
							|  |  |  | 	// 		promise....
 | 
					
						
							|  |  |  | 	// 			.concat(..)
 | 
					
						
							|  |  |  | 	// 			.push(..)
 | 
					
						
							|  |  |  | 	// 			.unshift(..)
 | 
					
						
							|  |  |  | 	// 			.first(..) / .last(..)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Overload .then(..), .catch(..) and .finally(..) to return a plain 
 | 
					
						
							|  |  |  | 	// Promise instnace...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: .catch(..) and .finally(..) are implemented through .then(..)
 | 
					
						
							|  |  |  | 	// 		so we do not need to overload those...
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 	then: function (onfulfilled, onrejected){ | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 		return new Promise( | 
					
						
							|  |  |  | 			function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 				Promise.prototype.then.call(this, | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 					// NOTE: resolve(..) / reject(..) return undefined so
 | 
					
						
							|  |  |  | 					// 		we can't pass them directly here...
 | 
					
						
							|  |  |  | 					function(res){  | 
					
						
							|  |  |  | 						resolve(res) | 
					
						
							|  |  |  | 						return res }, | 
					
						
							|  |  |  | 					function(res){ | 
					
						
							|  |  |  | 						reject(res) | 
					
						
							|  |  |  | 						return res }) }.bind(this)) | 
					
						
							|  |  |  | 			.then(...arguments) }, | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Promise.iter([ .. ])
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Promise.iter([ .. ], handler)
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	handler(e)
 | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	// 		-> [value]
 | 
					
						
							|  |  |  | 	// 		-> []
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: element index is unknowable untill the full list is expanded
 | 
					
						
							|  |  |  | 	// 		as handler(..)'s return value can expand to any number of 
 | 
					
						
							|  |  |  | 	// 		items...
 | 
					
						
							|  |  |  | 	// 		XXX we can make the index a promise, then if the client needs
 | 
					
						
							|  |  |  | 	// 			the value they can wait for it...
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-18 06:09:43 +03:00
										 |  |  | 	// Spectial cases usefull for extending this constructor...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//	Clone the iterator...
 | 
					
						
							|  |  |  | 	//	Promise.iter([ .. ], false)
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Create a rejected iterator...
 | 
					
						
							|  |  |  | 	//	Promise.iter(false)
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	__new__: function(_, list, handler){ | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 		var promise | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		// instance...
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 		var obj = Reflect.construct( | 
					
						
							|  |  |  | 			IterablePromise.__proto__,  | 
					
						
							|  |  |  | 			[function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 				// NOTE: this is here for Promise compatibilty...
 | 
					
						
							|  |  |  | 				if(typeof(list) == 'function'){ | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 					return list.call(this, ...arguments) }  | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 				// initial reject... 
 | 
					
						
							|  |  |  | 				if(list === false){ | 
					
						
							|  |  |  | 					return reject() } | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 				promise = {resolve, reject} }],  | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 			IterablePromise) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 		if(promise){ | 
					
						
							|  |  |  | 			// apply handler(..) to the list...
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 			//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 			// NOTE: the top level promises are not wrapped in arrays...
 | 
					
						
							|  |  |  | 			list = | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 				// apply the handler...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 				handler ? | 
					
						
							|  |  |  | 					list.map(function(block){ | 
					
						
							|  |  |  | 						return (block instanceof Array ?  | 
					
						
							|  |  |  | 								block  | 
					
						
							|  |  |  | 								: [block]) | 
					
						
							|  |  |  | 							.map(function(e){ | 
					
						
							|  |  |  | 								// NOTE: we are counting actual expanded 
 | 
					
						
							|  |  |  | 								// 		values and not the "blocks"...
 | 
					
						
							|  |  |  | 								return (e && e.then && e.catch) ? | 
					
						
							|  |  |  | 									// promise...
 | 
					
						
							|  |  |  | 									e.then(function(v){  | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 										return handler(v) }) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 									// basic value...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 									: handler(e) }) }) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 						.flat() | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 				// normal constructor...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 				: handler === undefined ? | 
					
						
							|  |  |  | 					list.map(function(e){  | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 						return e instanceof Promise ? | 
					
						
							|  |  |  | 							e | 
					
						
							|  |  |  | 							: [e] }) | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 				// clone...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 				: list.slice() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Object.defineProperty(obj, '__list', { | 
					
						
							|  |  |  | 				value: list, | 
					
						
							|  |  |  | 				enumerable: false, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// handle promise state...
 | 
					
						
							|  |  |  | 			Promise.all(list) | 
					
						
							|  |  |  | 				.then(function(res){ | 
					
						
							|  |  |  | 					promise.resolve(res.flat()) }) | 
					
						
							|  |  |  | 				.catch(promise.reject) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		return obj }, | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var InteractivePromise = | 
					
						
							|  |  |  | module.InteractivePromise = | 
					
						
							|  |  |  | object.Constructor('InteractivePromise', Promise, { | 
					
						
							|  |  |  | 	__message_handlers: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	send: function(...args){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		;(this.__message_handlers || []) | 
					
						
							|  |  |  | 			.forEach(function(h){ h.call(that, ...args) }) | 
					
						
							|  |  |  | 		return this }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	then: IterablePromise.prototype.then, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Promise.interactive(handler)
 | 
					
						
							|  |  |  | 	//		-> interacive-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	handler(resolve, reject, onmessage)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	onmessage(func)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	__new__: function(_, handler){ | 
					
						
							|  |  |  | 		var handlers = [] | 
					
						
							|  |  |  | 		var onmessage = function(func){ | 
					
						
							|  |  |  | 			handlers.push(func) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var obj = Reflect.construct( | 
					
						
							|  |  |  | 			InteractivePromise.__proto__,  | 
					
						
							|  |  |  | 			!handler ? | 
					
						
							|  |  |  | 				[] | 
					
						
							|  |  |  | 				: [function(resolve, reject){ | 
					
						
							|  |  |  | 					return handler(resolve, reject, onmessage) }],  | 
					
						
							|  |  |  | 			InteractivePromise) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Object.defineProperty(obj, '__message_handlers', { | 
					
						
							|  |  |  | 			value: handlers, | 
					
						
							|  |  |  | 			enumerable: false, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  |    		return obj }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var CooperativePromise = | 
					
						
							|  |  |  | module.CooperativePromise = | 
					
						
							|  |  |  | object.Constructor('CooperativePromise', Promise, { | 
					
						
							|  |  |  | 	__handlers: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get isSet(){ | 
					
						
							|  |  |  | 		return this.__handlers === false }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	set: function(value, resolve=true){ | 
					
						
							|  |  |  | 		// can't set twice...
 | 
					
						
							|  |  |  | 		if(this.isSet){ | 
					
						
							|  |  |  | 			throw new Error('.set(..): can not set twice') } | 
					
						
							|  |  |  | 		// bind to promise...
 | 
					
						
							|  |  |  | 		if(value && value.then && value.catch){ | 
					
						
							|  |  |  | 			value.then(handlers.resolve) | 
					
						
							|  |  |  | 			value.catch(handlers.reject) | 
					
						
							|  |  |  | 		// resolve with value...
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			resolve ? | 
					
						
							|  |  |  | 				this.__handlers.resolve(value)  | 
					
						
							|  |  |  | 				: this.__handlers.reject(value) } | 
					
						
							|  |  |  | 		// cleanup and prevent setting twice...
 | 
					
						
							|  |  |  | 		this.__handlers = false | 
					
						
							|  |  |  | 		return this }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	then: IterablePromise.prototype.then, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__new__: function(){ | 
					
						
							|  |  |  | 		var handlers | 
					
						
							|  |  |  | 		var resolver = arguments[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var obj = Reflect.construct( | 
					
						
							|  |  |  | 			CooperativePromise.__proto__,  | 
					
						
							|  |  |  | 			[function(resolve, reject){ | 
					
						
							|  |  |  | 				handlers = {resolve, reject}  | 
					
						
							|  |  |  | 				// NOTE: this is here to support builtin .then(..)
 | 
					
						
							|  |  |  | 				resolver | 
					
						
							|  |  |  | 					&& resolver(resolve, reject) }],  | 
					
						
							|  |  |  | 			CooperativePromise)  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Object.defineProperty(obj, '__handlers', { | 
					
						
							|  |  |  | 			value: handlers, | 
					
						
							|  |  |  | 			enumerable: false, | 
					
						
							|  |  |  | 			writable: true, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		return obj }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var PromiseMixin = | 
					
						
							|  |  |  | module.PromiseMixin = | 
					
						
							|  |  |  | object.Mixin('PromiseMixin', 'soft', { | 
					
						
							|  |  |  | 	iter: IterablePromise, | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 	interactive: InteractivePromise, | 
					
						
							|  |  |  | 	cooperative: CooperativePromise, | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PromiseMixin(Promise) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 18:24:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |