| 
									
										
										
										
											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. | 
					
						
							| 
									
										
										
										
											2022-06-14 10:37:01 +03:00
										 |  |  | * 		Similar to Promise.all(..) but adds basic iterator API. | 
					
						
							| 
									
										
										
										
											2021-01-05 04:49:24 +03:00
										 |  |  | * | 
					
						
							|  |  |  | * 	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') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | var generator = require('./generator') | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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: 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-14 10:37:01 +03:00
										 |  |  | // 		...mostly the current state is OK, but need more testing...
 | 
					
						
							| 
									
										
										
										
											2022-06-17 12:01:04 +03:00
										 |  |  | // XXX add support for async generators...
 | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | // 		
 | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | var EMPTY = {doc: 'empty placeholder'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | var iterPromiseProxy =  | 
					
						
							| 
									
										
										
										
											2022-06-15 03:44:24 +03:00
										 |  |  | module.iterPromiseProxy =  | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | function(name){ | 
					
						
							|  |  |  | 	return function(...args){ | 
					
						
							|  |  |  | 		return this.constructor( | 
					
						
							|  |  |  | 			this.then(function(lst){ | 
					
						
							|  |  |  | 				return lst[name](...args) })) } } | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:47:14 +03:00
										 |  |  | // XXX ASYNC should this be async or simply return a SyncPromise/Promise???
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | var promiseProxy = | 
					
						
							| 
									
										
										
										
											2022-06-15 03:44:24 +03:00
										 |  |  | module.promiseProxy = | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | function(name){ | 
					
						
							|  |  |  | 	return async function(...args){ | 
					
						
							|  |  |  | 		return (await this)[name](...args) } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | var IterablePromise = | 
					
						
							|  |  |  | module.IterablePromise = | 
					
						
							|  |  |  | object.Constructor('IterablePromise', Promise, { | 
					
						
							| 
									
										
										
										
											2022-06-13 19:43:45 +03:00
										 |  |  | 	get STOP(){ | 
					
						
							|  |  |  | 		return Array.STOP }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }, { | 
					
						
							| 
									
										
										
										
											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)...
 | 
					
						
							| 
									
										
										
										
											2022-06-13 13:26:31 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if 'types/Array' is imported this will support throwing STOP
 | 
					
						
							|  |  |  | 	// 		from the handler.
 | 
					
						
							|  |  |  | 	// 		Due to the async nature of promises though the way stops are 
 | 
					
						
							|  |  |  | 	// 		handled may be unpredictable -- the handlers can be run out 
 | 
					
						
							|  |  |  | 	// 		of order, as the nested promises resolve and thus throwing 
 | 
					
						
							|  |  |  | 	// 		stop will stop the handlers not yet run and not the next 
 | 
					
						
							|  |  |  | 	// 		handlers in sequence.
 | 
					
						
							|  |  |  | 	// 		XXX EXPEREMENTAL: STOP...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | 	// XXX ITER can we unwind (sync/async) generators one by one???
 | 
					
						
							| 
									
										
										
										
											2022-12-19 22:43:27 +03:00
										 |  |  | 	__pack: function(list, handler=undefined, onerror=undefined){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		// handle iterator...
 | 
					
						
							|  |  |  | 		// XXX ITER do we unwind the iterator here or wait to unwind later???
 | 
					
						
							|  |  |  | 		if(typeof(list) == 'object'  | 
					
						
							|  |  |  | 				&& Symbol.iterator in list){ | 
					
						
							|  |  |  | 			if(!onerror){ | 
					
						
							|  |  |  | 				list = [...list] | 
					
						
							|  |  |  | 			// handle errors in input generator...
 | 
					
						
							|  |  |  | 			// NOTE: this does not offer the most control because semantically 
 | 
					
						
							|  |  |  | 			// 		we bust behave in the same manner as <generator>.iter(..)
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var res = [] | 
					
						
							|  |  |  | 				try{ | 
					
						
							|  |  |  | 					for(var e of list){ | 
					
						
							|  |  |  | 						res.push(e) } | 
					
						
							|  |  |  | 				}catch(err){ | 
					
						
							|  |  |  | 					var r = onerror(err) | 
					
						
							|  |  |  | 					r !== undefined | 
					
						
							|  |  |  | 						&& res.push(r) }  | 
					
						
							|  |  |  | 				list = res } }  | 
					
						
							|  |  |  | 		// handle iterable promise...
 | 
					
						
							|  |  |  | 		if(list instanceof IterablePromise){ | 
					
						
							|  |  |  | 			return this.__handle(list.__packed, handler, onerror) } | 
					
						
							|  |  |  | 		// handle promise / async-iterator...
 | 
					
						
							|  |  |  | 		// XXX ITER do we unwind the iterator here or wait to unwind later???
 | 
					
						
							|  |  |  | 		if(typeof(list) == 'object'  | 
					
						
							|  |  |  | 					&& Symbol.asyncIterator in list){ | 
					
						
							|  |  |  | 			return list | 
					
						
							|  |  |  | 				.iter(handler, onerror)  | 
					
						
							|  |  |  | 				.then(function(list){ | 
					
						
							|  |  |  | 					return that.__pack(list) }) }  | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							|  |  |  | 			return list | 
					
						
							|  |  |  | 				.then(function(list){ | 
					
						
							|  |  |  | 					return that.__pack(list, handler, onerror) }) } | 
					
						
							|  |  |  | 		// pack...
 | 
					
						
							|  |  |  | 		list = [list].flat() | 
					
						
							|  |  |  | 			.map(function(elem){ | 
					
						
							|  |  |  | 				return elem instanceof Array ? | 
					
						
							|  |  |  | 						[elem] | 
					
						
							|  |  |  | 					: elem instanceof Promise ? | 
					
						
							|  |  |  | 						elem.then(function(e){ | 
					
						
							|  |  |  | 							return [e] }) | 
					
						
							|  |  |  | 					: elem }) | 
					
						
							|  |  |  | 		// handle if needed...
 | 
					
						
							|  |  |  | 		return handler ? | 
					
						
							|  |  |  | 			this.__handle(list, handler, onerror) | 
					
						
							|  |  |  | 			: list }, | 
					
						
							|  |  |  | 	// transform/handle packed array (sync, but can return promises in the list)...
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:34:31 +03:00
										 |  |  | 	// XXX need a strict spec...
 | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX BUG:
 | 
					
						
							|  |  |  | 	// 			await Promise.iter([1, [2], Promise.resolve(3), Promise.resolve([4])], e => [[1,2,3]])
 | 
					
						
							|  |  |  | 	//				-> [ 1, 2, 3, [ 1, 2, 3 ], [ 1, 2, 3 ], [ 1, 2, 3 ] ]
 | 
					
						
							|  |  |  | 	//		the first item should not be expanded...
 | 
					
						
							| 
									
										
										
										
											2022-12-19 22:43:27 +03:00
										 |  |  | 	__handle: function(list, handler=undefined, onerror=undefined){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		if(typeof(list) == 'function'){ | 
					
						
							|  |  |  | 			handler = list | 
					
						
							|  |  |  | 			list = this.__packed } | 
					
						
							|  |  |  | 		if(!handler){ | 
					
						
							|  |  |  | 			return list } | 
					
						
							|  |  |  | 		// handle promise list...
 | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							|  |  |  | 			return list.then(function(list){ | 
					
						
							|  |  |  | 				return that.__handle(list, handler, onerror) }) } | 
					
						
							|  |  |  | 		// do the work...
 | 
					
						
							|  |  |  | 		list = list instanceof Array ? | 
					
						
							|  |  |  | 			list | 
					
						
							|  |  |  | 			: [list] | 
					
						
							|  |  |  | 		var map = !!this.constructor.STOP ? | 
					
						
							|  |  |  | 			'smap' | 
					
						
							|  |  |  | 			: 'map' | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 		var stop = false | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 		// XXX do we handle generators here???
 | 
					
						
							|  |  |  | 		var each = function(elem){ | 
					
						
							|  |  |  | 			return elem instanceof Array ? | 
					
						
							|  |  |  | 				elem | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | 					//.map(handler)
 | 
					
						
							|  |  |  | 					// XXX can we avoid using EMPTY here and instead use .flat(..) ???
 | 
					
						
							|  |  |  | 					.map(function(elem){ | 
					
						
							|  |  |  | 						var res = handler(elem) | 
					
						
							|  |  |  | 						return res instanceof Promise ? | 
					
						
							|  |  |  | 							res.then(function(e){ | 
					
						
							|  |  |  | 								return (e instanceof Array  | 
					
						
							|  |  |  | 										&& e.length == 0) ? | 
					
						
							|  |  |  | 									EMPTY | 
					
						
							|  |  |  | 									: e }) | 
					
						
							|  |  |  | 							: res }) | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 					.flat() | 
					
						
							|  |  |  | 				: handler(elem) } | 
					
						
							| 
									
										
										
										
											2022-12-19 22:43:27 +03:00
										 |  |  | 		return list | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 			[map]( | 
					
						
							|  |  |  | 				function(elem){ | 
					
						
							| 
									
										
										
										
											2022-12-29 15:57:56 +03:00
										 |  |  | 					// NOTE: we are calling .flat() on the result so we 
 | 
					
						
							|  |  |  | 					// 		need to keep a handled array as a single 
 | 
					
						
							|  |  |  | 					// 		element by wrapping the return of handled(..)...
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 					return elem instanceof IterablePromise ? | 
					
						
							|  |  |  | 							(elem.isSync() ? | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 								each(elem.sync()) | 
					
						
							|  |  |  | 								: elem.iterthen(each)) | 
					
						
							| 
									
										
										
										
											2022-12-29 15:53:16 +03:00
										 |  |  | 						// sync sync promise...
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 						: (elem instanceof SyncPromise | 
					
						
							|  |  |  | 								&& !(elem.sync() instanceof Promise)) ? | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 							[each(elem.sync())] | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 						// promise / promise-like...
 | 
					
						
							|  |  |  | 						: elem && elem.then ? | 
					
						
							|  |  |  | 							// NOTE: when this is explicitly stopped we 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 15:53:16 +03:00
										 |  |  | 							// 		do not call any more handlers after 
 | 
					
						
							|  |  |  | 							// 		STOP is thrown/returned...
 | 
					
						
							| 
									
										
										
										
											2022-12-29 15:57:56 +03:00
										 |  |  | 							// NOTE: the promise protects this from .flat()
 | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 							elem.then(function(elem){ | 
					
						
							|  |  |  | 								return !stop ? | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 									each(elem) | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | 									: EMPTY }) | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 						: elem instanceof Array ? | 
					
						
							| 
									
										
										
										
											2023-01-04 02:35:15 +03:00
										 |  |  | 							[each(elem)] | 
					
						
							|  |  |  | 						: each(elem) }, | 
					
						
							| 
									
										
										
										
											2022-12-29 15:53:16 +03:00
										 |  |  | 				// handle STOP...
 | 
					
						
							|  |  |  | 				function(){ | 
					
						
							| 
									
										
										
										
											2022-12-29 03:53:54 +03:00
										 |  |  | 					stop = true }) | 
					
						
							| 
									
										
										
										
											2022-12-19 22:43:27 +03:00
										 |  |  |    			.flat() }, | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 	// XXX this should return IterablePromise if .__packed is partially sync (???)
 | 
					
						
							|  |  |  | 	// unpack array (sync/async)...
 | 
					
						
							|  |  |  | 	__unpack: function(list){ | 
					
						
							|  |  |  | 		list = list  | 
					
						
							|  |  |  | 			?? this.__packed | 
					
						
							|  |  |  | 		// handle promise list...
 | 
					
						
							|  |  |  | 		if(list instanceof IterablePromise){ | 
					
						
							|  |  |  | 			return list.__unpack() } | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							|  |  |  | 			return list | 
					
						
							|  |  |  | 				.then(this.__unpack.bind(this)) } | 
					
						
							|  |  |  | 		var res = [] | 
					
						
							|  |  |  | 		for(var e of list){ | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | 			if(e === EMPTY){ | 
					
						
							|  |  |  | 				continue } | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 			if(e instanceof IterablePromise){ | 
					
						
							|  |  |  | 				e = e.__unpack() } | 
					
						
							|  |  |  | 			if(e instanceof SyncPromise){ | 
					
						
							|  |  |  | 				e = e.sync() } | 
					
						
							|  |  |  | 			// give up on a sync solution...
 | 
					
						
							|  |  |  | 			if(e instanceof Promise){ | 
					
						
							|  |  |  | 				// XXX can we return an IterablePromise???
 | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | 				// XXX is there a more elegant way to do this???
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 				return Promise.all(list) | 
					
						
							|  |  |  | 					.then(function(list){  | 
					
						
							| 
									
										
										
										
											2023-01-07 12:38:29 +03:00
										 |  |  | 						// XXX do we need to handle EMPTY???
 | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | 						return list.flat() }) | 
					
						
							|  |  |  | 					.iter() } | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 			res.push(e) } | 
					
						
							|  |  |  | 		return res.flat() }, | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2022-08-19 18:02:40 +03:00
										 |  |  | 	[Symbol.asyncIterator]: async function*(){ | 
					
						
							|  |  |  | 		var list = this.__packed | 
					
						
							|  |  |  | 		if(list instanceof Promise){ | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 			yield* await this.__unpack(list)  | 
					
						
							| 
									
										
										
										
											2022-08-19 18:02:40 +03:00
										 |  |  | 			return } | 
					
						
							|  |  |  | 		for await(var elem of list){ | 
					
						
							|  |  |  | 			yield* elem instanceof Array ? | 
					
						
							|  |  |  | 				elem | 
					
						
							|  |  |  | 				: [elem] } }, | 
					
						
							| 
									
										
										
										
											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){ | 
					
						
							| 
									
										
										
										
											2023-01-06 12:30:24 +03:00
										 |  |  | 				return [func(e)] }) }, | 
					
						
							|  |  |  | 	// XXX BUG:
 | 
					
						
							|  |  |  | 	//			await Promise.iter([1, [2], 3])
 | 
					
						
							|  |  |  | 	//					.filter(e => Promise.resolve(false))
 | 
					
						
							|  |  |  | 	//				-> [ [] ]
 | 
					
						
							|  |  |  | 	//		should be:
 | 
					
						
							|  |  |  | 	//				-> []
 | 
					
						
							|  |  |  | 	//		...do we flatten the result of promise returned by handler???
 | 
					
						
							|  |  |  | 	//		XXX this might require a change in .__handle(..)
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 				return res instanceof Promise ? | 
					
						
							| 
									
										
										
										
											2023-01-06 12:30:24 +03:00
										 |  |  | 					res.then(function(res){ | 
					
						
							|  |  |  | 						// XXX this should be the same as the non-promise version...
 | 
					
						
							|  |  |  | 						return res ? | 
					
						
							|  |  |  | 							e | 
					
						
							|  |  |  | 							: [] }) | 
					
						
							|  |  |  | 					: res ? | 
					
						
							|  |  |  | 						[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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 	// XXX BETWEEN...
 | 
					
						
							|  |  |  | 	between: function(func){ | 
					
						
							| 
									
										
										
										
											2022-08-14 13:38:37 +03:00
										 |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		var j = 0 | 
					
						
							|  |  |  | 		var prev | 
					
						
							|  |  |  | 		return this.constructor(this, | 
					
						
							|  |  |  | 			function(e){ | 
					
						
							|  |  |  | 				return i++ > 0 ? | 
					
						
							|  |  |  | 					[ | 
					
						
							|  |  |  | 						typeof(func) == 'function' ? | 
					
						
							| 
									
										
										
										
											2022-08-14 13:46:22 +03:00
										 |  |  | 							func.call(this, [prev, e], i, i + j++) | 
					
						
							| 
									
										
										
										
											2022-08-14 13:38:37 +03:00
										 |  |  | 							: func, | 
					
						
							|  |  |  | 						e, | 
					
						
							|  |  |  | 					] | 
					
						
							|  |  |  | 					: [e] }) }, | 
					
						
							| 
									
										
										
										
											2022-08-14 11:15:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-21 13:49:50 +03:00
										 |  |  | 	// XXX .chain(..) -- see generator.chain(..)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-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-12-07 02:47:14 +03:00
										 |  |  | 	// XXX ASYNC should this be async or simply return a SyncPromise/Promise???
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2022-06-15 10:36:33 +03:00
										 |  |  | 					// XXX not sure if this is correct...
 | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 					|| 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.
 | 
					
						
							| 
									
										
										
										
											2022-06-13 19:43:45 +03:00
										 |  |  | 	// XXX is it faster to do .reverse().reduce(..) ???
 | 
					
						
							| 
									
										
										
										
											2022-06-11 19:35:35 +03:00
										 |  |  | 	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-13 20:10:09 +03:00
										 |  |  | 	// 		promises for values because any promise in .__packed makes 
 | 
					
						
							|  |  |  | 	// 		the value count/index non-deterministic...
 | 
					
						
							| 
									
										
										
										
											2022-06-09 11:12:39 +03:00
										 |  |  | 	sort: iterPromiseProxy('sort'), | 
					
						
							|  |  |  | 	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'), | 
					
						
							|  |  |  | 	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'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.find(<func>)
 | 
					
						
							|  |  |  | 	// 	.find(<func>, 'value')
 | 
					
						
							|  |  |  | 	// 		-> <promise>(<value>)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.find(<func>, 'result')
 | 
					
						
							|  |  |  | 	// 		-> <promise>(<result>)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	.find(<func>, 'bool')
 | 
					
						
							|  |  |  | 	// 		-> <promise>(<bool>)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this is slightly different to Array's .find(..) in that it 
 | 
					
						
							|  |  |  | 	// 		accepts the result value enabling returning both the value 
 | 
					
						
							|  |  |  | 	// 		itself ('value', default), the test function's result 
 | 
					
						
							|  |  |  | 	// 		('result') or true/false ('bool') -- this is added to be 
 | 
					
						
							|  |  |  | 	// 		able to distinguish between the undefined as a stored value 
 | 
					
						
							|  |  |  | 	// 		and undefined as a "nothing found" result.
 | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 	// NOTE: I do not get how essentially identical methods .some(..) 
 | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 	// 		and .find(..) got added to JS's Array...
 | 
					
						
							|  |  |  | 	// 		the only benefit is that .some(..) handles undefined values 
 | 
					
						
							|  |  |  | 	// 		stored in the array better...
 | 
					
						
							| 
									
										
										
										
											2022-06-13 19:43:45 +03:00
										 |  |  | 	// NOTE: this will return the result as soon as it's available but 
 | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 	// 		it will not stop the created but unresolved at the time 
 | 
					
						
							|  |  |  | 	// 		promises from executing, this is both good and bad:
 | 
					
						
							|  |  |  | 	// 		+ it will not break other clients waiting for promises 
 | 
					
						
							|  |  |  | 	// 			to resolve...
 | 
					
						
							|  |  |  | 	// 		- if no clients are available this can lead to wasted 
 | 
					
						
							|  |  |  | 	// 			CPU time...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:47:14 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX ASYNC should this be async or simply return a SyncPromise/Promise???
 | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 	find: async function(func, result='value'){ | 
					
						
							| 
									
										
										
										
											2022-06-13 19:43:45 +03:00
										 |  |  | 		var that = this | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 		// NOTE: not using pure await here as this is simpler to actually 
 | 
					
						
							|  |  |  | 		// 		control the moment the resulting promise resolves without 
 | 
					
						
							|  |  |  | 		// 		the need for juggling state...
 | 
					
						
							|  |  |  | 		return new Promise(function(resolve, reject){ | 
					
						
							|  |  |  | 			var resolved = false | 
					
						
							|  |  |  | 			that.map(function(elem){ | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 					var res = func(elem) | 
					
						
							|  |  |  | 					if(res){ | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 						resolved = true | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 						resolve( | 
					
						
							|  |  |  | 							result == 'bool' ? | 
					
						
							|  |  |  | 								true | 
					
						
							|  |  |  | 							: result == 'result' ? | 
					
						
							|  |  |  | 								res | 
					
						
							|  |  |  | 							: elem) | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 						// XXX EXPEREMENTAL: STOP...
 | 
					
						
							|  |  |  | 						// NOTE: we do not need to throw STOP here 
 | 
					
						
							|  |  |  | 						// 		but it can prevent some overhead...
 | 
					
						
							|  |  |  | 						if(that.constructor.STOP){ | 
					
						
							|  |  |  | 							throw that.constructor.STOP } } }) | 
					
						
							|  |  |  | 				.then(function(){ | 
					
						
							|  |  |  | 					resolved | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 						|| resolve( | 
					
						
							|  |  |  | 							result == 'bool' ? | 
					
						
							|  |  |  | 								false | 
					
						
							|  |  |  | 								: undefined) }) }) }, | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 	findIndex: promiseProxy('findIndex'), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 	// NOTE: this is just a special-case of .find(..)
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:47:14 +03:00
										 |  |  | 	// XXX ASYNC should this be async or simply return a SyncPromise/Promise???
 | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 	some: async function(func){ | 
					
						
							| 
									
										
										
										
											2022-06-13 22:48:07 +03:00
										 |  |  | 		return this.find(func, 'bool') }, | 
					
						
							| 
									
										
										
										
											2022-06-13 20:10:09 +03:00
										 |  |  | 	every: promiseProxy('every'), | 
					
						
							| 
									
										
										
										
											2022-06-09 01:33:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 01:02:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:47:14 +03:00
										 |  |  | 	// XXX ASYNC should this be async or simply return a SyncPromise/Promise???
 | 
					
						
							| 
									
										
										
										
											2022-07-27 14:11:01 +03:00
										 |  |  | 	join: async function(){ | 
					
						
							|  |  |  | 		return [...(await this)] | 
					
						
							|  |  |  | 			.join(...arguments) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 10:36:33 +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
										 |  |  | 	// 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...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: this is internally linked to the actual (via: ..then.call(this, ..)) 
 | 
					
						
							|  |  |  | 	// 		state and will be resolved in .__new__(..) below.
 | 
					
						
							|  |  |  | 	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 }, | 
					
						
							| 
									
										
										
										
											2022-12-07 02:47:14 +03:00
										 |  |  | 	// XXX EXPEREMENTAL revise...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 	// Like .then(..) but returns an IterablePromise instance...
 | 
					
						
							|  |  |  | 	iterthen: function(onfulfilled, onrejected){ | 
					
						
							|  |  |  | 		if(this.isSync()){ | 
					
						
							|  |  |  | 			var res = onfulfilled ? | 
					
						
							|  |  |  | 				this.constructor(onfulfilled(this.__unpack())) | 
					
						
							|  |  |  | 				: this.constructor(this.__unpack())  | 
					
						
							|  |  |  | 			onrejected | 
					
						
							|  |  |  | 				&& res.catch(onrejected)  | 
					
						
							|  |  |  | 			return res } | 
					
						
							|  |  |  | 		// XXX we need to feed the output of onfulfilled to the value of 
 | 
					
						
							|  |  |  | 		// 		res, but to this without wrapping the whole thing in a 
 | 
					
						
							|  |  |  | 		// 		promise (possible???)...
 | 
					
						
							|  |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			this.constructor(this.then(...arguments)) | 
					
						
							|  |  |  | 			: this.constructor(this.__packed, 'raw') }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX EXPEREMENTAL
 | 
					
						
							|  |  |  | 	isSync: function(){ | 
					
						
							|  |  |  | 		return !(this.__packed instanceof Promise | 
					
						
							|  |  |  | 			|| this.__packed | 
					
						
							|  |  |  | 				.filter(function(e){ | 
					
						
							|  |  |  | 					return e instanceof IterablePromise ? | 
					
						
							|  |  |  | 							!e.isSync() | 
					
						
							|  |  |  | 						: e instanceof Promise  | 
					
						
							|  |  |  | 								&& !(e instanceof SyncPromise) }) | 
					
						
							|  |  |  | 				.length > 0) }, | 
					
						
							|  |  |  | 	sync: function(error=false){ | 
					
						
							|  |  |  | 		try{ | 
					
						
							|  |  |  | 			var res = this.__unpack() | 
					
						
							|  |  |  | 		}catch(err){ | 
					
						
							|  |  |  | 			if(error == false){ | 
					
						
							|  |  |  | 				return } | 
					
						
							|  |  |  | 			if(typeof(error) == 'function'){ | 
					
						
							|  |  |  | 				return error(err) } | 
					
						
							|  |  |  | 			throw err } | 
					
						
							|  |  |  | 		return error !== false  | 
					
						
							|  |  |  | 				&& res instanceof Promise ? | 
					
						
							|  |  |  | 			// XXX should this be an IterablePromise???
 | 
					
						
							|  |  |  | 			res.catch(error) | 
					
						
							|  |  |  | 			: res }, | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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...
 | 
					
						
							| 
									
										
										
										
											2022-06-15 03:44:24 +03:00
										 |  |  | 	// 			...this may be quite an overhead...
 | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-06-13 13:26:31 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if 'types/Array' is imported this will support throwing STOP,
 | 
					
						
							|  |  |  | 	// 		for more info see notes for .__pack(..)
 | 
					
						
							|  |  |  | 	// 		XXX EXPEREMENTAL: STOP...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 23:41:26 +03:00
										 |  |  | 	__new__: function(_, list, handler=undefined, onerror=undefined){ | 
					
						
							| 
									
										
										
										
											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( | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 			Promise, | 
					
						
							|  |  |  | 			//this.constructor.__proto__,
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 			[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} }],  | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 			this.constructor) | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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'){ | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 				//list = list instanceof IterablePromise ?
 | 
					
						
							|  |  |  | 				list = list instanceof this.constructor ? | 
					
						
							| 
									
										
										
										
											2022-12-07 23:41:26 +03:00
										 |  |  | 					obj.__handle(list.__packed, handler, onerror) | 
					
						
							|  |  |  | 					: obj.__pack(list, handler, onerror) } | 
					
						
							| 
									
										
										
										
											2022-06-11 15:49:05 +03:00
										 |  |  | 			Object.defineProperty(obj, '__packed', { | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 				value: list, | 
					
						
							|  |  |  | 				enumerable: false, | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 				// NOTE: this is needed for self-resolve...
 | 
					
						
							|  |  |  | 				writable: true, | 
					
						
							| 
									
										
										
										
											2020-11-17 21:35:04 +03:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-11-17 16:12:13 +03:00
										 |  |  | 			// handle promise state...
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 			try{ | 
					
						
							|  |  |  | 				var res = obj.__unpack(list) | 
					
						
							|  |  |  | 			}catch(err){ | 
					
						
							|  |  |  | 				promise.reject(err) } | 
					
						
							|  |  |  | 			res instanceof Promise ? | 
					
						
							|  |  |  | 				res | 
					
						
							|  |  |  | 					.then(function(list){ | 
					
						
							|  |  |  | 						promise.resolve(list) }) | 
					
						
							|  |  |  | 					.catch(promise.reject)  | 
					
						
							|  |  |  | 				: promise.resolve(res)  | 
					
						
							|  |  |  | 			// XXX EXPEREMENTAL
 | 
					
						
							|  |  |  | 			// XXX do we handle errors here???
 | 
					
						
							|  |  |  | 			// self-resolve state...
 | 
					
						
							|  |  |  | 			list instanceof Promise ? | 
					
						
							|  |  |  | 				list.then(function(list){ | 
					
						
							|  |  |  | 					obj.__packed = list }) | 
					
						
							|  |  |  | 				: list.forEach(function(elem, i){ | 
					
						
							|  |  |  | 					elem instanceof Promise | 
					
						
							|  |  |  | 						&& elem.then(function(elem){ | 
					
						
							|  |  |  | 							lst = obj.__packed.slice() | 
					
						
							|  |  |  | 							lst[i] = elem | 
					
						
							|  |  |  | 							obj.__packed = lst }) }) } | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | 		return obj }, | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2022-12-15 19:09:42 +03:00
										 |  |  | // XXX EXPEREMENTAL/HACK...
 | 
					
						
							| 
									
										
										
										
											2023-01-04 07:06:59 +03:00
										 |  |  | // Sequential iterable promise...
 | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-04 03:47:37 +03:00
										 |  |  | // This like IterablePromise but guarantees handler execution in order 
 | 
					
						
							|  |  |  | // element occurrence.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // For comparison:
 | 
					
						
							|  |  |  | // 		Promise.all([ .. ]).then(func)
 | 
					
						
							|  |  |  | // 			- func is called on element list
 | 
					
						
							|  |  |  | // 			- func is called when all the elements are resolved
 | 
					
						
							|  |  |  | // 		Promise.iter([ .. ]).iter(func)
 | 
					
						
							|  |  |  | // 			- func per element
 | 
					
						
							|  |  |  | // 			- func is called when an element is resolved/ready 
 | 
					
						
							| 
									
										
										
										
											2023-01-04 07:06:59 +03:00
										 |  |  | // 				in order of resolution/readiness
 | 
					
						
							| 
									
										
										
										
											2023-01-04 03:47:37 +03:00
										 |  |  | // 		Promise.seqiter([ .. ]).iter(func)
 | 
					
						
							|  |  |  | // 			- func per element
 | 
					
						
							|  |  |  | // 			- func is called when an element is resolved/ready 
 | 
					
						
							|  |  |  | // 				and when all elements before it are handled
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: that here a promise will block handling of later promises even 
 | 
					
						
							|  |  |  | // 		if they are resolved before it.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-01-04 07:06:59 +03:00
										 |  |  | // XXX is this correct???
 | 
					
						
							|  |  |  | // 			> g = function*(){ yield* [1,2,3] }
 | 
					
						
							|  |  |  | //			// XXX should this expand the generator???
 | 
					
						
							|  |  |  | //			> await Promise.seqiter([0, g()])
 | 
					
						
							|  |  |  | //				-> [ 0, Object [Generator] {} ]
 | 
					
						
							|  |  |  | //			> await Promise.seqiter([0, g()]).flat()
 | 
					
						
							|  |  |  | //				-> [ 0, 1, 2, 3 ]
 | 
					
						
							| 
									
										
										
										
											2023-01-04 05:34:41 +03:00
										 |  |  | // XXX check if this behaves correctly (call order) on concatenation and
 | 
					
						
							|  |  |  | // 		other methods...
 | 
					
						
							| 
									
										
										
										
											2022-12-17 19:00:13 +03:00
										 |  |  | // XXX not sure if this is a viable strategy....
 | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | var IterableSequentialPromise = | 
					
						
							|  |  |  | module.IterableSequentialPromise = | 
					
						
							|  |  |  | object.Constructor('IterableSequentialPromise', IterablePromise, { | 
					
						
							| 
									
										
										
										
											2023-01-02 22:16:23 +03:00
										 |  |  | 	__pack: function(list, handler=undefined, onerror=undefined){ | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 		var seqiter = this.constructor | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 		var repack = function(list){ | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 			var res = [] | 
					
						
							|  |  |  | 			for(var [i, e] of list.entries()){ | 
					
						
							| 
									
										
										
										
											2023-01-04 06:39:55 +03:00
										 |  |  | 				if(e.then | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 						// skip last promise -- nothing to wrap...
 | 
					
						
							|  |  |  | 						&& i < list.length-1){ | 
					
						
							|  |  |  | 					res.push(e | 
					
						
							|  |  |  | 						.then(function(e){  | 
					
						
							| 
									
										
										
										
											2023-01-06 12:30:24 +03:00
										 |  |  | 							// NOTE: this does not call any handlers, thus
 | 
					
						
							|  |  |  | 							// 		there should be no risk of out of order 
 | 
					
						
							|  |  |  | 							// 		handler execution....
 | 
					
						
							| 
									
										
										
										
											2023-01-04 05:34:41 +03:00
										 |  |  | 							return seqiter( | 
					
						
							| 
									
										
										
										
											2023-01-04 06:39:55 +03:00
										 |  |  | 									[e, ...list.slice(i+1)]) | 
					
						
							| 
									
										
										
										
											2023-01-04 03:47:37 +03:00
										 |  |  | 								.flat() })) | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 					break } | 
					
						
							|  |  |  | 				res.push(e) } | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 			return res } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: we are not handling the list here...
 | 
					
						
							|  |  |  | 		list = object.parentCall(IterableSequentialPromise.prototype.__pack, this, list)  | 
					
						
							| 
									
										
										
										
											2023-01-04 03:47:37 +03:00
										 |  |  | 		list = list instanceof SyncPromise ? | 
					
						
							|  |  |  | 			list.sync() | 
					
						
							|  |  |  | 			: list | 
					
						
							| 
									
										
										
										
											2023-01-06 12:30:24 +03:00
										 |  |  | 		// repack...
 | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 		list = list instanceof Array ? | 
					
						
							|  |  |  | 				repack(list) | 
					
						
							| 
									
										
										
										
											2023-01-04 06:39:55 +03:00
										 |  |  | 			: list.then ? | 
					
						
							| 
									
										
										
										
											2023-01-03 04:13:15 +03:00
										 |  |  | 				list.then(repack) | 
					
						
							|  |  |  | 			: list  | 
					
						
							|  |  |  | 		return handler ? | 
					
						
							|  |  |  | 			this.__handle(list, handler, onerror) | 
					
						
							| 
									
										
										
										
											2023-01-03 02:43:03 +03:00
										 |  |  | 			: list }, | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +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.
 | 
					
						
							| 
									
										
										
										
											2022-06-15 03:44:24 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-24 20:23:22 +03:00
										 |  |  | // 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 }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:30:54 +03:00
										 |  |  | // XXX should this support async generators???
 | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | var syncAllProxy =  | 
					
						
							|  |  |  | function(name){ | 
					
						
							|  |  |  | 	return function(lst){ | 
					
						
							|  |  |  | 		var sync = true | 
					
						
							|  |  |  | 		for(var e of lst){ | 
					
						
							|  |  |  | 			if(e instanceof Promise  | 
					
						
							|  |  |  | 					&& !(e instanceof SyncPromise)){ | 
					
						
							|  |  |  | 				sync = false | 
					
						
							|  |  |  | 				break } } | 
					
						
							|  |  |  | 		return sync ? | 
					
						
							|  |  |  | 			this.resolve(lst) | 
					
						
							|  |  |  | 			: Promise[name](lst) } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX REVISE/TEST...
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:30:54 +03:00
										 |  |  | // XXX should this support async generators???
 | 
					
						
							| 
									
										
										
										
											2022-12-04 15:59:07 +03:00
										 |  |  | var syncAnyProxy = | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | function(name){ | 
					
						
							|  |  |  | 	return function(lst){ | 
					
						
							|  |  |  | 		for(var e of lst){ | 
					
						
							|  |  |  | 			if(e instanceof SyncPromise  | 
					
						
							|  |  |  | 					&& !('error' in e)){ | 
					
						
							|  |  |  | 				return e } | 
					
						
							|  |  |  | 			if(!(e instanceof Promise)){ | 
					
						
							|  |  |  | 				return this.resolve(e) } } | 
					
						
							|  |  |  | 		return Promise[name](list) } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | // XXX EXPEREMENTAL...
 | 
					
						
							|  |  |  | // XXX DOCS...
 | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | // XXX like promise but if a value can be generated sync then this will 
 | 
					
						
							|  |  |  | // 		run in sync otherwise it will fall back to being a promise...
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:10:22 +03:00
										 |  |  | // XXX should we throw errors in sync mode??? ...option???
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:29:37 +03:00
										 |  |  | var SyncPromise = | 
					
						
							|  |  |  | module.SyncPromise = | 
					
						
							|  |  |  | object.Constructor('SyncPromise', Promise, { | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 	// NOTE: we need to overload these as the builtin versions sneak-in 
 | 
					
						
							|  |  |  | 	// 		async-ness before we can catch it in .__new__(..)
 | 
					
						
							|  |  |  | 	resolve: function(value){ | 
					
						
							|  |  |  | 		return new this(function(resolve){ resolve(value) }) }, | 
					
						
							|  |  |  | 	reject: function(error){ | 
					
						
							|  |  |  | 		return new this(function(_, reject){ reject(error) }) }, | 
					
						
							| 
									
										
										
										
											2022-12-04 18:30:54 +03:00
										 |  |  | 	// NOTE: these essentially add a special case where the inputs are
 | 
					
						
							|  |  |  | 	// 		either not promises or SyncPromise instances...
 | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 	all: syncAllProxy('all'), | 
					
						
							|  |  |  | 	allSettled: syncAllProxy('allSettled'), | 
					
						
							|  |  |  | 	any: syncAnyProxy('any'), | 
					
						
							|  |  |  | 	race: syncAnyProxy('race'), | 
					
						
							|  |  |  | },{ | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 	//value: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:10:22 +03:00
										 |  |  | 	//error: undefined,
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:10:22 +03:00
										 |  |  | 	// NOTE: if this is called it means that .__new__(..) returned in sync 
 | 
					
						
							|  |  |  | 	// 		mode and thus set .value and possibly .error, soe there is no 
 | 
					
						
							|  |  |  | 	// 		need to check for .value...
 | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 	then: function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2022-12-04 17:01:15 +03:00
										 |  |  | 		return this.hasOwnProperty('error') ? | 
					
						
							|  |  |  | 				this.constructor.reject( | 
					
						
							|  |  |  | 					reject ? | 
					
						
							|  |  |  | 						reject(this.error) | 
					
						
							| 
									
										
										
										
											2022-12-04 17:02:01 +03:00
										 |  |  | 						: this.error) | 
					
						
							| 
									
										
										
										
											2022-12-04 17:01:15 +03:00
										 |  |  | 			: resolve ? | 
					
						
							|  |  |  | 				this.constructor.resolve( | 
					
						
							|  |  |  | 					resolve(this.value))  | 
					
						
							|  |  |  | 			// XXX should we return a copy???
 | 
					
						
							|  |  |  | 			: this }, | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 	sync: function(error='throw'){ | 
					
						
							|  |  |  | 		if(error !== false  | 
					
						
							|  |  |  | 				&& 'error' in this){ | 
					
						
							|  |  |  | 			if(typeof(error) != 'function'){ | 
					
						
							|  |  |  | 				throw this.error } | 
					
						
							|  |  |  | 			return error(this.error) } | 
					
						
							|  |  |  | 		return this.value }, | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:10:22 +03:00
										 |  |  | 	// NOTE: if func calls resolve(..) with a promise then this will return
 | 
					
						
							|  |  |  | 	// 		that promise...
 | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 	__new__: function(context, func){ | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 		var value | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 		var resolve = function(res){ | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 			return (value = res) } | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 		var rejected | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 		var error | 
					
						
							|  |  |  | 		var reject = function(err){ | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 			rejected = true | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 			return (error = err) } | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 		// call...
 | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 		try{ | 
					
						
							|  |  |  | 			func(resolve, reject) | 
					
						
							|  |  |  | 		}catch(err){ | 
					
						
							|  |  |  | 			reject(err) } | 
					
						
							|  |  |  | 		// async...
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 		if(!error  | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 				&& value instanceof Promise){ | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | 			return object.ASIS(value) } | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 		// sync...
 | 
					
						
							| 
									
										
										
										
											2022-12-04 15:58:28 +03:00
										 |  |  | 		var obj = Promise.resolve(value) | 
					
						
							|  |  |  | 		obj.value = value | 
					
						
							| 
									
										
										
										
											2022-12-04 05:01:34 +03:00
										 |  |  | 		rejected | 
					
						
							|  |  |  | 			&& (obj.error = error) | 
					
						
							|  |  |  | 		return obj }, | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 02:21:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 12:07:28 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 23:50:05 +03:00
										 |  |  | var PromiseMixin = | 
					
						
							|  |  |  | module.PromiseMixin = | 
					
						
							|  |  |  | object.Mixin('PromiseMixin', 'soft', { | 
					
						
							|  |  |  | 	iter: IterablePromise, | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	seqiter: IterableSequentialPromise, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 05:48:54 +03:00
										 |  |  | 	interactive: InteractivePromise, | 
					
						
							|  |  |  | 	cooperative: CooperativePromise, | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 05:29:37 +03:00
										 |  |  | 	sync: SyncPromise, | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 17:01:15 +03:00
										 |  |  | 	// XXX should this be implemented via SyncPromise??? 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:28:01 +03:00
										 |  |  | 	// XXX not sure if we need to expand async generators...
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:41:39 +03:00
										 |  |  | 	// 		(update README if this changes)
 | 
					
						
							| 
									
										
										
										
											2022-12-07 23:41:26 +03:00
										 |  |  | 	awaitOrRun: function(data, func, error){ | 
					
						
							| 
									
										
										
										
											2022-11-29 18:39:23 +03:00
										 |  |  | 		data = [...arguments] | 
					
						
							|  |  |  | 		func = data.pop() | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 		if(typeof(data.at(-1)) == 'function'){ | 
					
						
							|  |  |  | 			error = func | 
					
						
							|  |  |  | 			func = data.pop() } | 
					
						
							| 
									
										
										
										
											2022-12-08 01:28:01 +03:00
										 |  |  | 		error = error ?  | 
					
						
							|  |  |  | 			[error]  | 
					
						
							|  |  |  | 			: [] | 
					
						
							|  |  |  | 		// check if we need to await...
 | 
					
						
							|  |  |  | 		return data.reduce(function(res, e){ | 
					
						
							| 
									
										
										
										
											2022-11-29 18:39:23 +03:00
										 |  |  | 					return res  | 
					
						
							|  |  |  | 						|| e instanceof Promise }, false) ? | 
					
						
							| 
									
										
										
										
											2022-12-08 01:28:01 +03:00
										 |  |  | 				// NOTE: we will not reach this on empty data...
 | 
					
						
							|  |  |  | 				(data.length > 1 ? | 
					
						
							|  |  |  | 					Promise.all(data) | 
					
						
							|  |  |  | 						.then( | 
					
						
							|  |  |  | 							function(res){  | 
					
						
							|  |  |  | 								return func(...res) },  | 
					
						
							|  |  |  | 							...error) | 
					
						
							|  |  |  | 					: data[0].then(func, ...error)) | 
					
						
							|  |  |  | 			// XXX not sure if we need to expand async generators...
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:38:06 +03:00
										 |  |  | 			// 		...since it has .then(..) it can be treated as a promise...
 | 
					
						
							|  |  |  | 			// XXX should we just check for .then(..) ???
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:41:39 +03:00
										 |  |  | 			// XXX update README if this changes...
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:28:01 +03:00
										 |  |  | 			: (data.length == 1  | 
					
						
							|  |  |  | 					&& Symbol.asyncIterator in data[0] | 
					
						
							|  |  |  | 					&& 'then' in data[0]) ? | 
					
						
							|  |  |  | 				data[0].then(func, ...error) | 
					
						
							|  |  |  | 			: error.length > 0 ? | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 				function(){ | 
					
						
							|  |  |  | 					try{ | 
					
						
							| 
									
										
										
										
											2022-12-03 13:20:29 +03:00
										 |  |  | 						return func(...data) | 
					
						
							| 
									
										
										
										
											2022-12-03 13:17:11 +03:00
										 |  |  | 					}catch(err){ | 
					
						
							| 
									
										
										
										
											2022-12-08 01:28:01 +03:00
										 |  |  | 						return error[0](err) } }() | 
					
						
							| 
									
										
										
										
											2022-11-29 18:39:23 +03:00
										 |  |  | 			: func(...data) }, | 
					
						
							| 
									
										
										
										
											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-12-13 23:52:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 23:41:26 +03:00
										 |  |  | 	iter: function(handler=undefined, onerror=undefined){ | 
					
						
							|  |  |  | 		return IterablePromise(this, handler, onerror) }, | 
					
						
							| 
									
										
										
										
											2022-12-13 23:52:56 +03:00
										 |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	seqiter: function(handler=undefined, onerror=undefined){ | 
					
						
							|  |  |  | 		return IterableSequentialPromise(this, handler, onerror) }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 18:15:40 +03:00
										 |  |  | 	// unify the general promise API with other promise types...
 | 
					
						
							|  |  |  | 	// XXX should this be here???
 | 
					
						
							|  |  |  | 	// XXX error if given must return the result... (???)
 | 
					
						
							|  |  |  | 	sync: function(error){ | 
					
						
							|  |  |  | 		typeof(error) == 'function' | 
					
						
							|  |  |  | 			&& this.catch(error) | 
					
						
							| 
									
										
										
										
											2022-12-04 05:29:37 +03:00
										 |  |  | 		return this }, | 
					
						
							| 
									
										
										
										
											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 }) |