| 
									
										
										
										
											2020-11-02 18:24:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2021-01-05 04:49:24 +03:00
										 |  |  | * | 
					
						
							|  |  |  | * This defines the following extensions to Promise: | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * 	Promise.iter(seq) | 
					
						
							| 
									
										
										
										
											2022-06-09 11:46:05 +03:00
										 |  |  | * 	<promise>.iter() | 
					
						
							| 
									
										
										
										
											2021-01-05 04:49:24 +03:00
										 |  |  | * 		Iterable promise object. | 
					
						
							|  |  |  | * 		Similar to Promise.all(..) but adds basic iterator/generator | 
					
						
							|  |  |  | * 		API and will resolve the items as they are ready (resolved). | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * 	Promise.interactive(handler) | 
					
						
							|  |  |  | * 		Interactive promise object. | 
					
						
							|  |  |  | * 		This adds a basic message passing API to the promise. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * 	Promise.cooperative() | 
					
						
							|  |  |  | * 		Cooperative promise object. | 
					
						
							|  |  |  | * 		Exposes the API to resolve/reject the promise object  | 
					
						
							|  |  |  | * 		externally. | 
					
						
							|  |  |  | * | 
					
						
							| 
									
										
										
										
											2022-06-09 11:46:05 +03:00
										 |  |  | * 	<promise>.as(obj) | 
					
						
							|  |  |  | * 		Promise proxy. | 
					
						
							|  |  |  | * 		Proxies the methods available from obj to promise value. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							| 
									
										
										
										
											2021-01-05 04:49:24 +03:00
										 |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							| 
									
										
										
										
											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') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 08:46:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-24 20:23:22 +03:00
										 |  |  | // Iterable promise...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // Like Promise.all(..) but adds ability to iterate through results
 | 
					
						
							|  |  |  | // via generators .map(..)/.reduce(..) and friends...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | // NOTE: it would be nice to support throwing STOP (XXX) from the iterable 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 16:03:35 +03:00
										 |  |  | // 		promise but...
 | 
					
						
							|  |  |  | // 		- this is more complicated than simply using .smap(..) instead 
 | 
					
						
							|  |  |  | // 			of .map(..) because the list can contain async promises...
 | 
					
						
							|  |  |  | // 			...would need to wrap each .then(..) call in try-catch and
 | 
					
						
							|  |  |  | // 			manually handle the stop...
 | 
					
						
							|  |  |  | // 			...then there's a question of derivative iterators etc.
 | 
					
						
							|  |  |  | // 		- another issue here is that the stop would happen in order of 
 | 
					
						
							|  |  |  | // 			execution and not order of elements...
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:15:20 +03:00
										 |  |  | // 		XXX though stopping within a single level might be useful...
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | // NOTE: the following can not be implemented here:
 | 
					
						
							|  |  |  | // 			.splice(..)				- can't both modify and return
 | 
					
						
							|  |  |  | // 									  a result...
 | 
					
						
							|  |  |  | // 			.pop() / .shift()		- can't modify the promise, use 
 | 
					
						
							|  |  |  | // 									  .first() / .last() instead.
 | 
					
						
							|  |  |  | // 			[Symbol.iterator]()		- needs to be sync and we can't
 | 
					
						
							|  |  |  | // 									  know the number of elements to
 | 
					
						
							|  |  |  | // 									  return promises before the whole
 | 
					
						
							|  |  |  | // 									  iterable promise is resolved.
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:15:20 +03:00
										 |  |  | // NOTE: we are not using async/await here as we need to control the 
 | 
					
						
							|  |  |  | // 		type of promise returned in cases where we know we are returning 
 | 
					
						
							|  |  |  | // 		an array...
 | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | // NOTE: there is no point in implementing a 1:1 version of this that 
 | 
					
						
							|  |  |  | // 		would not support element expansion/contraction as it would only 
 | 
					
						
							|  |  |  | // 		simplify a couple of methods that are 1:1 (like .map(..) and 
 | 
					
						
							|  |  |  | // 		.some(..)) while methods like .filter(..) will throw everything
 | 
					
						
							|  |  |  | // 		back to the complex IterablePromise...
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | // 		
 | 
					
						
							|  |  |  | // XXX how do we handle errors/rejections???
 | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | // 		
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | // XXX should these be exported???
 | 
					
						
							|  |  |  | var iterPromiseProxy =  | 
					
						
							|  |  |  | //module.iterPromiseProxy = 
 | 
					
						
							|  |  |  | function(name){ | 
					
						
							|  |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		return this.constructor( | 
					
						
							|  |  |  | 			this.then(function(lst){ | 
					
						
							|  |  |  | 				return lst[name](...args) })) } } | 
					
						
							|  |  |  | var promiseProxy = | 
					
						
							|  |  |  | //module.promiseProxy =
 | 
					
						
							|  |  |  | function(name){ | 
					
						
							|  |  |  | 	return async function(...args){ | 
					
						
							|  |  |  | 		return (await this)[name](...args) } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | var IterablePromise = | 
					
						
							|  |  |  | module.IterablePromise = | 
					
						
							|  |  |  | object.Constructor('IterablePromise', Promise, { | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// packed array...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Holds promise state.
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	[
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 	//		<non-array-value>,
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//		[ <value> ],
 | 
					
						
							|  |  |  | 	//		<promise>,
 | 
					
						
							|  |  |  | 	//		...
 | 
					
						
							|  |  |  | 	// 	]
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-08 16:03:35 +03:00
										 |  |  | 	// This format has several useful features:
 | 
					
						
							| 
									
										
										
										
											2022-06-12 12:36:45 +03:00
										 |  |  | 	// 	- concatenating packed lists results in a packed list
 | 
					
						
							| 
									
										
										
										
											2022-06-08 16:03:35 +03:00
										 |  |  | 	// 	- adding an iterable promise (as-is) into a packed list results 
 | 
					
						
							|  |  |  | 	// 		in a packed list
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 	// NOTE: in general iterable promises are implicitly immutable, so
 | 
					
						
							| 
									
										
										
										
											2022-06-12 12:36:45 +03:00
										 |  |  | 	// 		it is not recomended to ever edit this in-place...
 | 
					
						
							|  |  |  | 	// NOTE: we are not isolating or "protecting" any internals to 
 | 
					
						
							|  |  |  | 	// 		enable users to responsibly extend the code.
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 	__packed: null, | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 	// low-level .__packed handlers/helpers...
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 	// NOTE: these can be useful for debugging and extending...
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// pack and oprionally transform/handle an array (sync)...
 | 
					
						
							|  |  |  | 	__pack: function(list, handler=undefined){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		// handle iterable promise list...
 | 
					
						
							|  |  |  | 		if(list instanceof IterablePromise){ | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 			return this.__handle(list.__packed, handler) } | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		// handle promise list...
 | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							|  |  |  | 			return list.then(function(list){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 				return that.__pack(list, handler) }) } | 
					
						
							|  |  |  | 		// do the work...
 | 
					
						
							|  |  |  | 		// NOTE: packing and handling are mixed here because it's faster
 | 
					
						
							|  |  |  | 		// 		to do them both on a single list traverse...
 | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		var handle = !!handler | 
					
						
							|  |  |  | 		handler = handler  | 
					
						
							|  |  |  | 			?? function(elem){  | 
					
						
							|  |  |  | 				return [elem] } | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:31:38 +03:00
										 |  |  | 		//* XXX EXPEREMENTAL: STOP...
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 		var stoppable = !!Array.STOP | 
					
						
							|  |  |  | 		var stop = false | 
					
						
							|  |  |  | 		var map = stoppable ? | 
					
						
							|  |  |  | 			'smap' | 
					
						
							|  |  |  | 			: 'map' | 
					
						
							|  |  |  | 		var _handler = handler | 
					
						
							|  |  |  | 		handler = !handler.stoppable ? | 
					
						
							|  |  |  | 			Object.assign( | 
					
						
							|  |  |  | 				function(){ | 
					
						
							|  |  |  | 					try{ | 
					
						
							|  |  |  | 						return !stop ? | 
					
						
							|  |  |  | 							_handler(...arguments) | 
					
						
							|  |  |  | 							: [] | 
					
						
							|  |  |  | 					}catch(err){ | 
					
						
							|  |  |  | 						stop = err | 
					
						
							|  |  |  | 						if(err === Array.STOP | 
					
						
							|  |  |  | 								|| err instanceof Array.STOP){ | 
					
						
							|  |  |  | 							return 'value' in err ? | 
					
						
							|  |  |  | 								err.value | 
					
						
							|  |  |  | 								: [] } | 
					
						
							|  |  |  | 						throw err } }, | 
					
						
							|  |  |  | 				// prevent double+ wrapping...
 | 
					
						
							|  |  |  | 				// XXX revise nameing...
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:31:38 +03:00
										 |  |  | 				// XXX do we need this???
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 				{ stoppable: true }) | 
					
						
							|  |  |  | 			: handler | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		return [list].flat() | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 			// XXX supporting STOP here would require both using .smap(..)
 | 
					
						
							|  |  |  | 			// 		and tracking STOPs thrown in promises -- this could
 | 
					
						
							|  |  |  | 			// 		throw things out of sync for us not to be able to
 | 
					
						
							|  |  |  | 			// 		guarantee a full stop if a throw happened in a delayed
 | 
					
						
							|  |  |  | 			// 		handler effectively making the handlers race for the
 | 
					
						
							|  |  |  | 			// 		throw...
 | 
					
						
							|  |  |  | 			// 		...not sure if this is good or not...
 | 
					
						
							|  |  |  | 			[map](function(elem){ | 
					
						
							| 
									
										
										
										
											2022-06-13 03:31:38 +03:00
										 |  |  | 		/*/ | 
					
						
							|  |  |  | 		return [list].flat() | 
					
						
							|  |  |  | 			.map(function(elem){ | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 				return elem && elem.then ? | 
					
						
							|  |  |  | 						//that.__pack(elem, handler)
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 						//elem.then(handler)
 | 
					
						
							|  |  |  | 						elem | 
					
						
							|  |  |  | 							.then(handler) | 
					
						
							|  |  |  | 							.catch(function(err){ | 
					
						
							|  |  |  | 								stop = err | 
					
						
							|  |  |  | 								if(err === Array.STOP | 
					
						
							|  |  |  | 										|| err instanceof Array.STOP){ | 
					
						
							|  |  |  | 									return 'value' in err ? | 
					
						
							|  |  |  | 										err.value | 
					
						
							|  |  |  | 										: [] } | 
					
						
							|  |  |  | 								throw err }) | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 					: elem instanceof Array ? | 
					
						
							|  |  |  | 						handler(elem) | 
					
						
							|  |  |  | 					// NOTE: we keep things that do not need protecting 
 | 
					
						
							|  |  |  | 					// 		from .flat() as-is...
 | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 					: !handle ? | 
					
						
							|  |  |  | 						elem | 
					
						
							|  |  |  | 					: handler(elem) }) }, | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// transform/handle packed array (sync)...
 | 
					
						
							|  |  |  | 	__handle: function(list, handler=undefined){ | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		if(typeof(list) == 'function'){ | 
					
						
							|  |  |  | 			handler = list | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 			list = this.__packed } | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		if(!handler){ | 
					
						
							|  |  |  | 			return list } | 
					
						
							|  |  |  | 		// handle promise list...
 | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							|  |  |  | 			return list.then(function(list){ | 
					
						
							|  |  |  | 				return that.__handle(list, handler) }) } | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 		// do the work...
 | 
					
						
							|  |  |  | 		// NOTE: since each section of the packed .__array is the same 
 | 
					
						
							|  |  |  | 		// 		structure as the input we'll use .__pack(..) to handle 
 | 
					
						
							|  |  |  | 		// 		them, this also keeps all the handling code in one place.
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:31:38 +03:00
										 |  |  | 		//* XXX EXPEREMENTAL: STOP...
 | 
					
						
							| 
									
										
										
										
											2022-06-13 03:27:47 +03:00
										 |  |  | 		var map = !!Array.STOP ? | 
					
						
							|  |  |  | 			'smap' | 
					
						
							|  |  |  | 			: 'map' | 
					
						
							|  |  |  | 		return list[map](function(elem){ | 
					
						
							| 
									
										
										
										
											2022-06-13 03:31:38 +03:00
										 |  |  | 		/*/ | 
					
						
							|  |  |  | 		return list.map(function(elem){ | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 			return elem instanceof Array ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 					that.__pack(elem, handler) | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 				: elem instanceof Promise ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 					that.__pack(elem, handler) | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 						.then(function(elem){ | 
					
						
							|  |  |  | 							return elem.flat() }) | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 				: [handler(elem)] }) | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  |    			.flat() }, | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// unpack array (async)...
 | 
					
						
							|  |  |  | 	__unpack: async function(list){ | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		list = list  | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 			?? this.__packed | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		// handle promise list...
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 		return list instanceof Promise ? | 
					
						
							|  |  |  | 			this.__unpack(await list) | 
					
						
							|  |  |  | 			// do the work...
 | 
					
						
							|  |  |  | 			: (await Promise.all(list)) | 
					
						
							|  |  |  | 				.flat() }, | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 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...
 | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 	// NOTE: index of items is unknowable because items can expand and
 | 
					
						
							| 
									
										
										
										
											2022-06-11 11:36:13 +03:00
										 |  |  | 	// 		contract depending on handlers (e.g. .filter(..) can remove 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	// 		items)...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 	map: function(func){ | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 		return this.constructor(this,  | 
					
						
							| 
									
										
										
										
											2021-05-26 11:57:21 +03:00
										 |  |  | 			function(e){ | 
					
						
							| 
									
										
										
										
											2022-06-06 12:29:13 +03:00
										 |  |  | 				var res = func(e) | 
					
						
							|  |  |  | 				return res instanceof Promise ? | 
					
						
							|  |  |  | 		   			res.then(function(e){  | 
					
						
							|  |  |  | 						return [e] }) | 
					
						
							|  |  |  | 					: [res] }) }, | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	filter: function(func){ | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 		return this.constructor(this,  | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 			function(e){ | 
					
						
							| 
									
										
										
										
											2022-06-06 12:29:13 +03:00
										 |  |  | 				var res = func(e) | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 				var _filter = function(elem){ | 
					
						
							|  |  |  | 					return res ? | 
					
						
							|  |  |  | 						[elem] | 
					
						
							|  |  |  | 						: [] } | 
					
						
							| 
									
										
										
										
											2022-06-06 12:29:13 +03:00
										 |  |  | 				return res instanceof Promise ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 					res.then(_filter) | 
					
						
							|  |  |  | 					: _filter(e) }) }, | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 	// NOTE: this does not return an iterable promise as we can't know 
 | 
					
						
							|  |  |  | 	// 		what the user reduces to...
 | 
					
						
							| 
									
										
										
										
											2022-06-02 12:05:37 +03:00
										 |  |  | 	// NOTE: the items can be handled out of order because the nested 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:54:14 +03:00
										 |  |  | 	// 		promises can resolve in any order...
 | 
					
						
							| 
									
										
										
										
											2022-06-02 12:05:37 +03:00
										 |  |  | 	// NOTE: since order of execution can not be guaranteed there is no
 | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | 	// 		point in implementing .reduceRight(..) in the same way 
 | 
					
						
							|  |  |  | 	// 		(see below)...
 | 
					
						
							| 
									
										
										
										
											2021-05-26 11:57:21 +03:00
										 |  |  | 	reduce: function(func, res){ | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 		return this.constructor(this,  | 
					
						
							| 
									
										
										
										
											2021-05-26 11:57:21 +03:00
										 |  |  | 				function(e){ | 
					
						
							|  |  |  | 					res = func(res, e) | 
					
						
							|  |  |  | 					return [] }) | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 			.then(function(){  | 
					
						
							|  |  |  | 				return res }) }, | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 	flat: function(depth=1){ | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 		return this.constructor(this,  | 
					
						
							| 
									
										
										
										
											2021-05-26 11:57:21 +03:00
										 |  |  | 			function(e){  | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 				return (depth > 1  | 
					
						
							|  |  |  | 							&& e != null  | 
					
						
							|  |  |  | 							&& e.flat) ?  | 
					
						
							|  |  |  | 						e.flat(depth-1)  | 
					
						
							|  |  |  | 					: depth != 0 ? | 
					
						
							|  |  |  | 						e | 
					
						
							|  |  |  | 					: [e] }) }, | 
					
						
							| 
									
										
										
										
											2022-06-02 12:05:37 +03:00
										 |  |  | 	reverse: function(){ | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 		var lst = this.__packed | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 		return this.constructor( | 
					
						
							|  |  |  | 			lst instanceof Promise ? | 
					
						
							|  |  |  | 				lst.then(function(elems){ | 
					
						
							|  |  |  | 					return elems instanceof Array ? | 
					
						
							|  |  |  | 						elems.slice() | 
					
						
							| 
									
										
										
										
											2022-06-02 12:05:37 +03:00
										 |  |  | 							.reverse() | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 						: elems }) | 
					
						
							|  |  |  | 			: lst | 
					
						
							|  |  |  | 				.map(function(elems){ | 
					
						
							|  |  |  | 					return elems instanceof Array ? | 
					
						
							| 
									
										
										
										
											2022-06-03 21:23:23 +03:00
										 |  |  | 							elems.slice() | 
					
						
							|  |  |  | 								.reverse() | 
					
						
							|  |  |  | 						: elems instanceof Promise ? | 
					
						
							|  |  |  | 							elems.then(function(elems){ | 
					
						
							|  |  |  | 								return elems.reverse() }) | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 						: elems }) | 
					
						
							|  |  |  | 				.reverse(), | 
					
						
							|  |  |  | 			'raw') }, | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 	// NOTE: the following methods can create an unresolved promise from 
 | 
					
						
							|  |  |  | 	// 		a resolved promise...
 | 
					
						
							| 
									
										
										
										
											2022-06-04 03:01:54 +03:00
										 |  |  | 	concat: function(other){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		var cur = this.__pack(this) | 
					
						
							|  |  |  | 		var other = this.__pack(other) | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 		return this.constructor( | 
					
						
							| 
									
										
										
										
											2022-06-08 03:38:47 +03:00
										 |  |  | 			// NOTE: we need to keep things as exposed as possible, this 
 | 
					
						
							|  |  |  | 			// 		is why we're not blanketing all the cases with 
 | 
					
						
							|  |  |  | 			// 		Promise.all(..)...
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 			(cur instanceof Promise  | 
					
						
							|  |  |  | 					&& other instanceof Promise) ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:38:47 +03:00
										 |  |  | 				[cur, other] | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 			: cur instanceof Promise ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:38:47 +03:00
										 |  |  | 				[cur, ...other] | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 			: other instanceof Promise ? | 
					
						
							| 
									
										
										
										
											2022-06-08 03:38:47 +03:00
										 |  |  | 				[...cur, other] | 
					
						
							| 
									
										
										
										
											2022-06-08 03:45:06 +03:00
										 |  |  | 			: [...cur, ...other], | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 			'raw') }, | 
					
						
							| 
									
										
										
										
											2022-06-04 03:01:54 +03:00
										 |  |  | 	push: function(elem){ | 
					
						
							|  |  |  | 		return this.concat([elem]) }, | 
					
						
							|  |  |  | 	unshift: function(elem){ | 
					
						
							|  |  |  | 		return this.constructor([elem]) | 
					
						
							|  |  |  | 			.concat(this) }, | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | 	// XXX thses need to stop once an element is found so we cant simply 
 | 
					
						
							|  |  |  | 	// 		use .map(..) or .reduce(..)...
 | 
					
						
							|  |  |  | 	// XXX .find(func) / .findIndex(func)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// proxy methods...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// These require the whole promise to resolve to trigger.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// An exception to this would be .at(0)/.first() and .at(-1)/.last()
 | 
					
						
							|  |  |  | 	// that can get the target element if it's accessible.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: methods that are guaranteed to return an array will return
 | 
					
						
							|  |  |  | 	// 		an iterable promise (created with iterPromiseProxy(..))...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 	at: async function(i){ | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 		var list = this.__packed | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 		return ((i != 0 && i != -1) | 
					
						
							|  |  |  | 					|| list instanceof Promise | 
					
						
							|  |  |  | 					|| list.at(i) instanceof Promise) ? | 
					
						
							|  |  |  | 				(await this).at(i) | 
					
						
							|  |  |  | 			// NOTE: we can only reason about first/last explicit elements, 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 			// 		anything else is non-deterministic...
 | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 			: list.at(i) instanceof Promise ? | 
					
						
							|  |  |  | 				[await list.at(i)].flat().at(i) | 
					
						
							|  |  |  | 			: list.at(i) instanceof Array ? | 
					
						
							|  |  |  | 				list.at(i).at(i) | 
					
						
							|  |  |  | 			: list.at(i) }, | 
					
						
							|  |  |  | 	first: function(){ | 
					
						
							|  |  |  | 		return this.at(0) }, | 
					
						
							|  |  |  | 	last: function(){ | 
					
						
							|  |  |  | 		return this.at(-1) }, | 
					
						
							| 
									
										
										
										
											2022-06-04 03:10:49 +03:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | 	// NOTE: unlike .reduce(..) this needs the parent fully resolved 
 | 
					
						
							|  |  |  | 	// 		to be able to iterate from the end.
 | 
					
						
							|  |  |  | 	// XXX ???
 | 
					
						
							|  |  |  | 	reduceRight: promiseProxy('reduceRight'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	// NOTE: there is no way we can do a sync generator returning 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 	// 		promises for values because any promise in .__packed makes the 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	// 		value count/index non-deterministic...
 | 
					
						
							|  |  |  | 	sort: iterPromiseProxy('sort'), | 
					
						
							| 
									
										
										
										
											2022-06-11 14:45:10 +03:00
										 |  |  | 	// XXX we could have a special-case here for .slice()/slice(0, -1)
 | 
					
						
							|  |  |  | 	// 		and possibly othets, should we???
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	slice: iterPromiseProxy('slice'), | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	entries: iterPromiseProxy('entries'), | 
					
						
							|  |  |  | 	keys: iterPromiseProxy('keys'), | 
					
						
							|  |  |  | 	// XXX we could possibly make this better via .map(..)
 | 
					
						
							|  |  |  | 	values: iterPromiseProxy('values'), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	indexOf: promiseProxy('indexOf'), | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | 	lastIndexOf: promiseProxy('lastIndexOf'), | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	includes: promiseProxy('includes'), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	every: promiseProxy('every'), | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// XXX this can be lazy... (???)
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	some: promiseProxy('some'), | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// promise api...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	// 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...
 | 
					
						
							| 
									
										
										
										
											2021-04-07 14:47:25 +03:00
										 |  |  | 	// NOTE: this is slightly different from .then(..) in that it can be 
 | 
					
						
							|  |  |  | 	// 		called without arguments and return a promise wrapper. This can
 | 
					
						
							|  |  |  | 	// 		be useful to hide special promise functionality...
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 	then: function (onfulfilled, onrejected){ | 
					
						
							| 
									
										
										
										
											2021-04-07 14:47:25 +03:00
										 |  |  | 		var p = new Promise( | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 			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)) | 
					
						
							| 
									
										
										
										
											2021-04-07 14:47:25 +03:00
										 |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			p.then(...arguments)  | 
					
						
							|  |  |  | 			: p }, | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 16:04:56 +03:00
										 |  |  | 	// this is defined globally as Promise.prototype.iter(.,)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// for details see: PromiseMixin(..) below...
 | 
					
						
							|  |  |  | 	//iter: function(handler=undefined){ ... },
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:35:16 +03:00
										 |  |  | 	// constructor...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Promise.iter([ .. ])
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Promise.iter([ .. ], handler)
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	handler(e)
 | 
					
						
							| 
									
										
										
										
											2022-06-09 22:49:43 +03:00
										 |  |  | 	// 		-> [value, ..]
 | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	// 		-> []
 | 
					
						
							| 
									
										
										
										
											2022-06-09 22:49:43 +03:00
										 |  |  | 	// 		-> <promise>
 | 
					
						
							| 
									
										
										
										
											2020-11-16 02:38:19 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:54:14 +03:00
										 |  |  | 	// NOTE: element index is unknowable until the full list is expanded
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	// 		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
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:54:14 +03:00
										 |  |  | 	// Special cases useful for extending this constructor...
 | 
					
						
							| 
									
										
										
										
											2020-11-18 06:09:43 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 	//	Set raw .__packed without any pre-processing...
 | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 	//	Promise.iter([ .. ], 'raw')
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-03 21:23:23 +03:00
										 |  |  | 	//	Create a rejected iterator...
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 	//	Promise.iter(false)
 | 
					
						
							|  |  |  | 	//		-> iterable-promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 	__new__: function(_, list, handler){ | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		// instance...
 | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 		var promise | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 		var obj = Reflect.construct( | 
					
						
							|  |  |  | 			IterablePromise.__proto__,  | 
					
						
							|  |  |  | 			[function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:58:43 +03:00
										 |  |  | 				// NOTE: this is here for Promise compatibility...
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 				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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-08 16:03:35 +03:00
										 |  |  | 		// populate new instance...
 | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 		if(promise){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:54:14 +03:00
										 |  |  | 			// handle/pack input data...
 | 
					
						
							| 
									
										
										
										
											2022-06-03 19:41:13 +03:00
										 |  |  | 			if(handler != 'raw'){ | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 				list = list instanceof IterablePromise ? | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 					this.__handle(list.__packed, handler) | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 					: this.__pack(list, handler) } | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 			Object.defineProperty(obj, '__packed', { | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 				value: list, | 
					
						
							|  |  |  | 				enumerable: false, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 			// handle promise state...
 | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 			this.__unpack(list) | 
					
						
							| 
									
										
										
										
											2022-06-07 20:58:34 +03:00
										 |  |  | 				.then(function(list){ | 
					
						
							|  |  |  | 					promise.resolve(list) }) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 				.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
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-24 20:23:22 +03:00
										 |  |  | // Interactive promise...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // Adds ability to send messages to the running promise.
 | 
					
						
							|  |  |  | // 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var InteractivePromise = | 
					
						
							|  |  |  | module.InteractivePromise = | 
					
						
							|  |  |  | object.Constructor('InteractivePromise', Promise, { | 
					
						
							| 
									
										
										
										
											2021-04-07 03:32:23 +03:00
										 |  |  | 	// XXX do we need a way to remove handlers???
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 	__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 = [] | 
					
						
							| 
									
										
										
										
											2021-04-07 03:32:23 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 		var onmessage = function(func){ | 
					
						
							| 
									
										
										
										
											2021-04-07 12:30:38 +03:00
										 |  |  | 			// remove all handlers...
 | 
					
						
							| 
									
										
										
										
											2021-04-07 03:32:23 +03:00
										 |  |  | 			if(func === false){ | 
					
						
							| 
									
										
										
										
											2021-04-07 12:30:38 +03:00
										 |  |  | 				var h = (obj == null ? | 
					
						
							|  |  |  | 					handlers | 
					
						
							|  |  |  | 					: (obj.__message_handlers || [])) | 
					
						
							|  |  |  | 				h.splice(0, handlers.length) | 
					
						
							|  |  |  | 			// remove a specific handler...
 | 
					
						
							| 
									
										
										
										
											2021-04-07 03:32:23 +03:00
										 |  |  | 			} else if(arguments[1] === false){ | 
					
						
							|  |  |  | 				var h = (obj == null ? | 
					
						
							|  |  |  | 					handlers | 
					
						
							|  |  |  | 					: (obj.__message_handlers || [])) | 
					
						
							|  |  |  | 				h.splice(h.indexOf(func), 1) | 
					
						
							|  |  |  | 			// register a handler...
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var h = obj == null ? | 
					
						
							| 
									
										
										
										
											2022-06-11 16:04:56 +03:00
										 |  |  | 					// NOTE: we need to get the handlers from 
 | 
					
						
							|  |  |  | 					// 		.__message_handlers unless we are not 
 | 
					
						
							|  |  |  | 					// 		fully defined yet, then use the bootstrap 
 | 
					
						
							|  |  |  | 					// 		container (handlers)...
 | 
					
						
							|  |  |  | 					// 		...since we can call onmessage(..) while 
 | 
					
						
							|  |  |  | 					// 		the promise is still defined there is no 
 | 
					
						
							|  |  |  | 					// 		way to .send(..) until it returns a promise 
 | 
					
						
							|  |  |  | 					// 		object, this races here are highly unlikely...
 | 
					
						
							| 
									
										
										
										
											2021-04-07 03:32:23 +03:00
										 |  |  | 					handlers | 
					
						
							|  |  |  | 					: (obj.__message_handlers =  | 
					
						
							|  |  |  | 						obj.__message_handlers ?? []) | 
					
						
							|  |  |  | 				handlers.push(func) } } | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		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, | 
					
						
							| 
									
										
										
										
											2021-04-07 12:30:38 +03:00
										 |  |  | 			// XXX should this be .configurable???
 | 
					
						
							|  |  |  | 			configurable: true, | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 		}) | 
					
						
							|  |  |  |    		return obj }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-24 20:23:22 +03:00
										 |  |  | // Cooperative promise...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // A promise that can be resolved/rejected externally.
 | 
					
						
							|  |  |  | // NOTE: normally this has no internal resolver logic...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 12:12:00 +03:00
										 |  |  | // XXX EXPEREMENTAL...
 | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | var ProxyPromise = | 
					
						
							|  |  |  | module.ProxyPromise = | 
					
						
							|  |  |  | object.Constructor('ProxyPromise', Promise, { | 
					
						
							| 
									
										
										
										
											2022-06-11 16:04:56 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	then: IterablePromise.prototype.then, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | 	__new__: function(context, other, nooverride=false){ | 
					
						
							|  |  |  | 		var proto = 'prototype' in other ? | 
					
						
							|  |  |  | 			other.prototype | 
					
						
							|  |  |  | 			: other | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | 		var obj = Reflect.construct( | 
					
						
							|  |  |  | 			ProxyPromise.__proto__,  | 
					
						
							|  |  |  | 			[function(resolve, reject){ | 
					
						
							|  |  |  | 				context.then(resolve) | 
					
						
							|  |  |  | 				context.catch(reject) }],  | 
					
						
							|  |  |  | 			ProxyPromise)  | 
					
						
							|  |  |  | 		// populate...
 | 
					
						
							|  |  |  | 		// NOTE: we are not using object.deepKeys(..) here as we need 
 | 
					
						
							|  |  |  | 		// 		the key origin not to trigger property getters...
 | 
					
						
							|  |  |  | 		var seen = new Set() | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | 		nooverride = nooverride instanceof Array ? | 
					
						
							|  |  |  | 			new Set(nooverride) | 
					
						
							|  |  |  | 			: nooverride | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | 		while(proto != null){ | 
					
						
							|  |  |  | 			Object.entries(Object.getOwnPropertyDescriptors(proto)) | 
					
						
							|  |  |  | 				.forEach(function([key, value]){ | 
					
						
							|  |  |  | 					// skip overloaded keys...
 | 
					
						
							|  |  |  | 					if(seen.has(key)){ | 
					
						
							|  |  |  | 						return } | 
					
						
							|  |  |  | 					// skip non-functions...
 | 
					
						
							|  |  |  | 					if(typeof(value.value) != 'function'){ | 
					
						
							|  |  |  | 						return } | 
					
						
							|  |  |  | 					// skip non-enumerable except for Object.prototype.run(..)...
 | 
					
						
							|  |  |  | 					if(!(key == 'run'  | 
					
						
							|  |  |  | 								&& Object.prototype.run === value.value)  | 
					
						
							|  |  |  | 							&& !value.enumerable){ | 
					
						
							|  |  |  | 						return } | 
					
						
							| 
									
										
										
										
											2022-06-12 10:28:01 +03:00
										 |  |  | 					// do not override existing methods...
 | 
					
						
							|  |  |  | 					if(nooverride === true ?  | 
					
						
							|  |  |  | 								key in obj | 
					
						
							|  |  |  | 							: nooverride instanceof Set ? | 
					
						
							|  |  |  | 								nooverride.has(key) | 
					
						
							|  |  |  | 							: nooverride){ | 
					
						
							|  |  |  | 						return } | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | 					// proxy...
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 					obj[key] = promiseProxy(key) }) | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | 			proto = proto.__proto__ }  | 
					
						
							|  |  |  | 		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) | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var PromiseProtoMixin = | 
					
						
							|  |  |  | module.PromiseProtoMixin = | 
					
						
							|  |  |  | object.Mixin('PromiseProtoMixin', 'soft', { | 
					
						
							|  |  |  | 	as: ProxyPromise, | 
					
						
							| 
									
										
										
										
											2022-06-11 16:04:56 +03:00
										 |  |  | 	iter: function(handler=undefined){ | 
					
						
							| 
									
										
										
										
											2022-06-08 03:10:36 +03:00
										 |  |  | 		return IterablePromise(this, handler) }, | 
					
						
							| 
									
										
										
										
											2022-06-01 16:15:30 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | PromiseProtoMixin(Promise.prototype) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 18:24:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2022-06-11 13:53:24 +03:00
										 |  |  | * vim:set ts=4 sw=4 nowrap :                        */ return module }) |