| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							| 
									
										
										
										
											2020-10-09 03:24:25 +03:00
										 |  |  | * XXX move .zip(..) here from diff.js | 
					
						
							|  |  |  | * XXX do we need .at(..) / .to(..) methods here and in Map/Set/...??? | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							| 
									
										
										
										
											2020-10-06 01:32:33 +03:00
										 |  |  | **********************************************/  /* c8 ignore next 2 */ | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | var object = require('ig-object') | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 06:59:56 +03:00
										 |  |  | var generator = require('./generator') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 03:12:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | var StopIteration = | 
					
						
							|  |  |  | module.StopIteration = | 
					
						
							|  |  |  | 	object.Constructor('StopIteration', Error, { | 
					
						
							|  |  |  | 		// NOTE: I do not get why JavaScript's Error implements this 
 | 
					
						
							|  |  |  | 		// 		statically...
 | 
					
						
							|  |  |  | 		get name(){ | 
					
						
							|  |  |  | 			return this.constructor.name },  | 
					
						
							|  |  |  | 		// NOTE: msg is handled by Error(..)
 | 
					
						
							|  |  |  | 		__init__: function(msg){ | 
					
						
							|  |  |  | 			this.msg = msg }, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 03:12:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2020-10-15 03:12:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | // Array.prototype.flat polyfill...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: .flat(..) is not yet supported in IE/Edge...
 | 
					
						
							|  |  |  | Array.prototype.flat | 
					
						
							|  |  |  | 	|| (Array.prototype.flat = function(depth){ | 
					
						
							|  |  |  | 		depth = typeof(depth) == typeof(123) ? depth : 1 | 
					
						
							|  |  |  | 		return this.reduce(function(res, e){  | 
					
						
							|  |  |  | 			return res.concat(e instanceof Array && depth > 0 ?  | 
					
						
							|  |  |  | 				e.flat(depth-1)  | 
					
						
							|  |  |  | 				: [e]) }, []) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Array.prototype.includes polyfill...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | Array.prototype.includes | 
					
						
							|  |  |  | 	|| (Array.prototype.includes = function(value){ | 
					
						
							|  |  |  | 		return this.indexOf(value) >= 0 })  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // first/last element access short-hands...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	.first()
 | 
					
						
							|  |  |  | //	.last()
 | 
					
						
							|  |  |  | //		-> elem
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	.first(value)
 | 
					
						
							|  |  |  | //	.last(value)
 | 
					
						
							|  |  |  | //		-> array
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: setting a value will overwrite an existing first/last value.
 | 
					
						
							|  |  |  | // NOTE: for an empty array both .first(..)/.last(..) will return undefined 
 | 
					
						
							|  |  |  | // 		when getting a value and set the 0'th value when setting...
 | 
					
						
							| 
									
										
										
										
											2020-10-09 03:03:24 +03:00
										 |  |  | // NOTE: decided to keep these as methods and not props because methods
 | 
					
						
							|  |  |  | // 		have one advantage: they can be chained
 | 
					
						
							|  |  |  | // 		...while you can't chain assignment unless you wrap it in .run(..)
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | Array.prototype.first | 
					
						
							|  |  |  | 	|| (Array.prototype.first = function(value){ | 
					
						
							|  |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			((this[0] = value), this) | 
					
						
							|  |  |  | 			: this[0]}) | 
					
						
							|  |  |  | Array.prototype.last | 
					
						
							|  |  |  | 	|| (Array.prototype.last = function(value){ | 
					
						
							|  |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			((this[this.length - 1 || 0] = value), this) | 
					
						
							|  |  |  | 			: this[this.length - 1]}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-16 18:55:31 +03:00
										 |  |  | // Roll left/right (in-place)...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: to .rol(..) left just pass a negative n value...
 | 
					
						
							|  |  |  | // NOTE: we can't use ...[..] for sparse arrays as the will expand undefined
 | 
					
						
							|  |  |  | // 		inplace of empty positions, this is thereason the .splice(..) 
 | 
					
						
							|  |  |  | // 		implementation was replaced by a less clear (but faster)
 | 
					
						
							|  |  |  | // 		.copyWithin(..) version...
 | 
					
						
							|  |  |  | Array.prototype.rol | 
					
						
							|  |  |  | 	|| (Array.prototype.rol = function(n=1){ | 
					
						
							|  |  |  | 		var l = this.length | 
					
						
							|  |  |  | 		n = (n >= 0 ?  | 
					
						
							|  |  |  | 				n  | 
					
						
							|  |  |  | 				: l - n) | 
					
						
							|  |  |  | 			% l | 
					
						
							|  |  |  | 		if(n != 0){ | 
					
						
							|  |  |  | 			this.length += n | 
					
						
							|  |  |  | 			this.copyWithin(l, 0, n) | 
					
						
							|  |  |  | 			this.splice(0, n) } | 
					
						
							|  |  |  | 		return this }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | // Compact a sparse array...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will not compact in-place.
 | 
					
						
							|  |  |  | Array.prototype.compact = function(){ | 
					
						
							|  |  |  | 	return this.filter(function(){ return true }) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // like .length but for sparse arrays will return the element count...
 | 
					
						
							| 
									
										
										
										
											2020-10-09 03:03:24 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 'len' in Array.prototype | 
					
						
							|  |  |  | 	|| Object.defineProperty(Array.prototype, 'len', { | 
					
						
							|  |  |  | 		get : function () { | 
					
						
							| 
									
										
										
										
											2020-11-16 18:55:31 +03:00
										 |  |  | 			// NOTE: if we don't do .slice() here this can count array 
 | 
					
						
							|  |  |  | 			// 		instance attributes...
 | 
					
						
							|  |  |  | 			return Object.keys(this.slice()).length }, | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 		set : function(val){}, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | // Return a new array with duplicate elements removed...
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // NOTE: order is preserved... 
 | 
					
						
							|  |  |  | Array.prototype.unique = function(normalize){ | 
					
						
							|  |  |  | 	return normalize ?  | 
					
						
							|  |  |  | 		[...new Map(this.map(function(e){ return [normalize(e), e] })).values()] | 
					
						
							| 
									
										
										
										
											2020-11-16 18:55:31 +03:00
										 |  |  | 		// NOTE: we are calling .compact() here to avoid creating undefined 
 | 
					
						
							|  |  |  | 		// 		items from empty slots in sparse arrays...
 | 
					
						
							|  |  |  | 		: [...new Set(this.compact())] } | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | Array.prototype.tailUnique = function(normalize){ | 
					
						
							|  |  |  | 	return this | 
					
						
							|  |  |  | 		.slice() | 
					
						
							|  |  |  | 		.reverse() | 
					
						
							|  |  |  | 		.unique(normalize) | 
					
						
							|  |  |  | 		.reverse() } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-07 16:46:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | // Compare two arrays...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-09 03:03:24 +03:00
										 |  |  | // NOTE: this is diffectent from Object.match(..) in that this compares 
 | 
					
						
							|  |  |  | // 		self to other (internal) while match compares two entities 
 | 
					
						
							|  |  |  | // 		externally.
 | 
					
						
							|  |  |  | // 		XXX not sure if we need the destinction in name, will have to 
 | 
					
						
							|  |  |  | // 			come back to this when refactoring diff.js -- all three have
 | 
					
						
							|  |  |  | // 			to be similar...
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | Array.prototype.cmp = function(other){ | 
					
						
							|  |  |  | 	if(this === other){ | 
					
						
							|  |  |  | 		return true } | 
					
						
							|  |  |  | 	if(this.length != other.length){ | 
					
						
							|  |  |  | 		return false } | 
					
						
							|  |  |  | 	for(var i=0; i<this.length; i++){ | 
					
						
							|  |  |  | 		if(this[i] != other[i]){ | 
					
						
							|  |  |  | 			return false } } | 
					
						
							|  |  |  | 	return true } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Compare two Arrays as sets...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-07 16:46:59 +03:00
										 |  |  | // NOTE: this will ignore order and repeating elments...
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | Array.prototype.setCmp = function(other){ | 
					
						
							|  |  |  | 	return this === other  | 
					
						
							| 
									
										
										
										
											2020-10-07 16:46:59 +03:00
										 |  |  | 		|| (new Set([...this, ...other])).length == (new Set(this)).length } | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | // Sort as the other array...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | // 	Sort as array placing the sorted items at head...
 | 
					
						
							|  |  |  | // 	.sortAs(array)
 | 
					
						
							|  |  |  | // 	.sortAs(array, 'head')
 | 
					
						
							|  |  |  | // 		-> sorted
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Sort as array placing the sorted items at tail...
 | 
					
						
							|  |  |  | // 	.sortAs(array, 'tail')
 | 
					
						
							|  |  |  | // 		-> sorted
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | // This will sort the intersecting items in the head keeping the rest 
 | 
					
						
							|  |  |  | // of the items in the same relative order...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: if an item is in the array multiple times only the first index 
 | 
					
						
							|  |  |  | // 		is used...
 | 
					
						
							| 
									
										
										
										
											2020-10-09 03:24:25 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // XXX should this extend/patch .sort(..)???
 | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | // 		...currently do not see a clean way to do this without extending 
 | 
					
						
							|  |  |  | // 		and replacing Array or directly re-wrapping .sort(..)...
 | 
					
						
							|  |  |  | Array.prototype.sortAs = function(other, place='head'){ | 
					
						
							|  |  |  | 	place = place == 'tail' ? -1 : 1  | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | 	// NOTE: the memory overhead here is better than the time overhead 
 | 
					
						
							|  |  |  | 	// 		when using .indexOf(..)...
 | 
					
						
							|  |  |  | 	other = other.toMap() | 
					
						
							|  |  |  | 	var orig = this.toMap() | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 	return this.sort(function(a, b){ | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | 		var i = other.get(a) | 
					
						
							|  |  |  | 		var j = other.get(b) | 
					
						
							|  |  |  | 		return i == null && j == null ? | 
					
						
							|  |  |  | 				orig.get(a) - orig.get(b) | 
					
						
							|  |  |  | 			: i == null ?  | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | 				place | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | 			: j == null ?  | 
					
						
							| 
									
										
										
										
											2020-11-16 05:18:55 +03:00
										 |  |  | 				-place | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 			: i - j }) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | // Same as .sortAs(..) but will not change indexes of items not in other...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-09 03:24:25 +03:00
										 |  |  | // Example:
 | 
					
						
							|  |  |  | // 		['a', 3, 'b', 1, 2, 'c']
 | 
					
						
							|  |  |  | // 			.inplaceSortAs([1, 2, 3, 3]) // -> ['a', 1, 'b', 2, 3, 'c']
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | Array.prototype.inplaceSortAs = function(other){ | 
					
						
							|  |  |  | 	// sort only the intersection...
 | 
					
						
							|  |  |  | 	var sorted = this | 
					
						
							|  |  |  | 		.filter(function(e){  | 
					
						
							|  |  |  | 			return other.includes(e) }) | 
					
						
							|  |  |  | 		.sortAs(other) | 
					
						
							| 
									
										
										
										
											2020-10-09 03:03:24 +03:00
										 |  |  | 	// "zip" the sorted items back into this...
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | 	this.forEach(function(e, i, l){ | 
					
						
							|  |  |  | 		other.includes(e)  | 
					
						
							|  |  |  | 			&& (l[i] = sorted.shift()) }) | 
					
						
							|  |  |  | 	return this } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:25:25 +03:00
										 |  |  | // Equivalent to .map(..) / .filter(..) / .reduce(..) / .. with support for
 | 
					
						
							|  |  |  | // StopIteration...
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // NOTE: these add almost no overhead to the iteration.
 | 
					
						
							| 
									
										
										
										
											2020-11-16 18:55:31 +03:00
										 |  |  | // NOTE: these will not return a partial result if stopped.
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:25:25 +03:00
										 |  |  | // 
 | 
					
						
							|  |  |  | // XXX should these return a partial result on StopIteration?
 | 
					
						
							|  |  |  | var wrapIterFunc = function(iter){ | 
					
						
							|  |  |  | 	return function(func){ | 
					
						
							|  |  |  | 		try { | 
					
						
							|  |  |  | 			return this[iter](...arguments) | 
					
						
							|  |  |  | 		} catch(err){ | 
					
						
							|  |  |  | 			if(err === StopIteration){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} else if( err instanceof StopIteration){ | 
					
						
							|  |  |  | 				return err.msg } | 
					
						
							|  |  |  | 			throw err } } } | 
					
						
							|  |  |  | Array.prototype.smap = wrapIterFunc('map') | 
					
						
							|  |  |  | Array.prototype.sfilter = wrapIterFunc('filter') | 
					
						
							|  |  |  | Array.prototype.sreduce = wrapIterFunc('reduce') | 
					
						
							|  |  |  | Array.prototype.sforEach = wrapIterFunc('forEach') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:43:16 +03:00
										 |  |  | // Equivalent to .map(..) / .filter(..) / .reduce(..) that process the 
 | 
					
						
							|  |  |  | // contents in chunks asynchronously...
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	.mapChunks(func)
 | 
					
						
							|  |  |  | //	.mapChunks(chunk_size, func)
 | 
					
						
							|  |  |  | //	.mapChunks([item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //	.mapChunks(chunk_size, [item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //		-> promise(list)
 | 
					
						
							|  |  |  | //	
 | 
					
						
							|  |  |  | //	.filterChunks(func)
 | 
					
						
							|  |  |  | //	.filterChunks(chunk_size, func)
 | 
					
						
							|  |  |  | //	.filterChunks([item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //	.filterChunks(chunk_size, [item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //		-> promise(list)
 | 
					
						
							|  |  |  | //	
 | 
					
						
							|  |  |  | //	.reduceChunks(func, res)
 | 
					
						
							|  |  |  | //	.reduceChunks(chunk_size, func, res)
 | 
					
						
							|  |  |  | //	.reduceChunks([item_handler, chunk_handler], res)
 | 
					
						
							|  |  |  | //	.reduceChunks(chunk_size, [item_handler, chunk_handler], res)
 | 
					
						
							|  |  |  | //		-> promise(res)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	chunk_handler(chunk, result, offset)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // chunk_size can be:
 | 
					
						
							|  |  |  | // 	20			- chunk size
 | 
					
						
							|  |  |  | // 	'20'		- chunk size
 | 
					
						
							|  |  |  | // 	'20C'		- number of chunks
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // StopIteration can be thrown in func or chunk_handler at any time to 
 | 
					
						
							|  |  |  | // abort iteration, this will reject the promise.
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | //	
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The main goal of this is to not block the runtime while processing a 
 | 
					
						
							|  |  |  | // very long array by interrupting the processing with a timeout...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:25:25 +03:00
										 |  |  | // XXX should these return a partial result on StopIteration?
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | // XXX add generators:
 | 
					
						
							|  |  |  | // 			.map(..) / .filter(..) / .reduce(..)
 | 
					
						
							|  |  |  | // 		...the basis here should be the chunks, i.e. each cycle should
 | 
					
						
							|  |  |  | // 		go through a chunk...
 | 
					
						
							|  |  |  | //		...the mixin can be generic, i.e. applicable to Array, and 
 | 
					
						
							|  |  |  | //		other stuff...
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | var makeChunkIter = function(iter, wrapper){ | 
					
						
							|  |  |  | 	wrapper = wrapper | 
					
						
							|  |  |  | 		|| function(res, func, array, e){ | 
					
						
							|  |  |  | 			return func.call(this, e[1], e[0], array) } | 
					
						
							|  |  |  | 	return function(size, func, ...rest){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		var args = [...arguments] | 
					
						
							|  |  |  | 		size = (args[0] instanceof Function  | 
					
						
							|  |  |  | 				|| args[0] instanceof Array) ?  | 
					
						
							|  |  |  | 			(this.CHUNK_SIZE || 50) | 
					
						
							|  |  |  | 			: args.shift() | 
					
						
							|  |  |  | 		size = typeof(size) == typeof('str') ? | 
					
						
							|  |  |  | 				// number of chunks...
 | 
					
						
							|  |  |  | 				(size.trim().endsWith('c') || size.trim().endsWith('C') ? | 
					
						
							|  |  |  | 				 	Math.round(this.length / (parseInt(size) || 1)) || 1 | 
					
						
							|  |  |  | 				: parseInt(size)) | 
					
						
							|  |  |  | 			: size | 
					
						
							|  |  |  | 		var postChunk | 
					
						
							|  |  |  | 		func = args.shift() | 
					
						
							|  |  |  | 		;[func, postChunk] = func instanceof Array ? func : [func] | 
					
						
							|  |  |  | 		rest = args | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 04:29:12 +03:00
										 |  |  | 		// special case...
 | 
					
						
							|  |  |  | 		// no need to setTimeout(..) if smaller than size...
 | 
					
						
							|  |  |  | 		if(this.length <= size){ | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | 			try { | 
					
						
							|  |  |  | 				// handle iteration...
 | 
					
						
							|  |  |  | 				var res = this[iter](func, ...rest) | 
					
						
							|  |  |  | 				// handle chunk...
 | 
					
						
							|  |  |  | 				postChunk | 
					
						
							|  |  |  | 					&& postChunk.call(this, this, res, 0)  | 
					
						
							|  |  |  | 				return Promise.all(res)  | 
					
						
							|  |  |  | 			// handle StopIteration...
 | 
					
						
							|  |  |  | 			} catch(err){ | 
					
						
							|  |  |  | 				if(err === StopIteration){ | 
					
						
							|  |  |  | 					return Promise.reject()  | 
					
						
							|  |  |  | 				} else if( err instanceof StopIteration){ | 
					
						
							|  |  |  | 					return Promise.reject(err.msg) } | 
					
						
							|  |  |  | 				throw err } } | 
					
						
							| 
									
										
										
										
											2020-11-02 04:43:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var res = [] | 
					
						
							|  |  |  | 		var _wrapper = wrapper.bind(this, res, func, this) | 
					
						
							| 
									
										
										
										
											2020-11-02 04:29:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 		return new Promise(function(resolve, reject){ | 
					
						
							|  |  |  | 				var next = function(chunks){ | 
					
						
							|  |  |  | 					setTimeout(function(){ | 
					
						
							|  |  |  | 						var chunk, val | 
					
						
							| 
									
										
										
										
											2020-11-05 16:40:41 +03:00
										 |  |  | 						try { | 
					
						
							|  |  |  | 							// handle iteration...
 | 
					
						
							|  |  |  | 							res.push( | 
					
						
							|  |  |  | 								val = (chunk = chunks.shift())[iter](_wrapper, ...rest)) | 
					
						
							|  |  |  | 							// handle chunk...
 | 
					
						
							|  |  |  | 							postChunk | 
					
						
							|  |  |  | 								&& postChunk.call(that,  | 
					
						
							|  |  |  | 									chunk.map(function([i, v]){ return v }),  | 
					
						
							|  |  |  | 									val, | 
					
						
							|  |  |  | 									chunk[0][0]) | 
					
						
							|  |  |  | 						// handle StopIteration...
 | 
					
						
							|  |  |  | 						} catch(err){ | 
					
						
							|  |  |  | 							if(err === StopIteration){ | 
					
						
							|  |  |  | 								return reject()  | 
					
						
							|  |  |  | 							} else if( err instanceof StopIteration){ | 
					
						
							|  |  |  | 								return reject(err.msg) } | 
					
						
							|  |  |  | 							throw err } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 						// stop condition...
 | 
					
						
							|  |  |  | 						chunks.length == 0 ? | 
					
						
							|  |  |  | 							resolve(res.flat(2)) | 
					
						
							|  |  |  | 							: next(chunks) }, 0) } | 
					
						
							|  |  |  | 				next(that | 
					
						
							|  |  |  | 					// split the array into chunks...
 | 
					
						
							|  |  |  | 					.reduce(function(res, e, i){ | 
					
						
							|  |  |  | 						var c = res.slice(-1)[0] | 
					
						
							|  |  |  | 						c.length >= size ? | 
					
						
							|  |  |  | 							// initial element in chunk...
 | 
					
						
							|  |  |  | 							res.push([[i, e]]) | 
					
						
							|  |  |  | 							// rest...
 | 
					
						
							|  |  |  | 							: c.push([i, e]) | 
					
						
							|  |  |  | 						return res }, [[]])) }) } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array.prototype.CHUNK_SIZE = 50  | 
					
						
							|  |  |  | Array.prototype.mapChunks = makeChunkIter('map') | 
					
						
							|  |  |  | Array.prototype.filterChunks = makeChunkIter('map',  | 
					
						
							|  |  |  | 	function(res, func, array, e){ | 
					
						
							|  |  |  | 		return !!func.call(this, e[1], e[0], array) ? [e[1]] : [] }) | 
					
						
							|  |  |  | Array.prototype.reduceChunks = makeChunkIter('reduce', | 
					
						
							|  |  |  | 	function(total, func, array, res, e){ | 
					
						
							|  |  |  | 		return func.call(this,  | 
					
						
							|  |  |  | 			total.length > 0 ?  | 
					
						
							|  |  |  | 				total.pop()  | 
					
						
							|  |  |  | 				: res,  | 
					
						
							|  |  |  | 			e[1], e[0], array) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-07 16:46:59 +03:00
										 |  |  | // Convert an array to object...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Format:
 | 
					
						
							|  |  |  | // 	{
 | 
					
						
							|  |  |  | // 		<item>: <index>,
 | 
					
						
							|  |  |  | // 		...
 | 
					
						
							|  |  |  | // 	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: items should be strings, other types will get converted to 
 | 
					
						
							|  |  |  | // 		strings and thus may mess things up.
 | 
					
						
							|  |  |  | // NOTE: this will forget repeating items...
 | 
					
						
							|  |  |  | // NOTE: normalize will slow things down...
 | 
					
						
							|  |  |  | Array.prototype.toKeys = function(normalize){ | 
					
						
							|  |  |  | 	return normalize ?  | 
					
						
							|  |  |  | 		this.reduce(function(r, e, i){ | 
					
						
							|  |  |  | 			r[normalize(e)] = i | 
					
						
							|  |  |  | 			return r }, {}) | 
					
						
							|  |  |  | 		: this.reduce(function(r, e, i){ | 
					
						
							|  |  |  | 			r[e] = i | 
					
						
							|  |  |  | 			return r }, {}) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Convert an array to a map...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This is similar to Array.prototype.toKeys(..) but does not restrict 
 | 
					
						
							|  |  |  | // value type to string.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Format:
 | 
					
						
							|  |  |  | // 	Map([
 | 
					
						
							|  |  |  | // 		[<item>, <index>],
 | 
					
						
							|  |  |  | // 		...
 | 
					
						
							|  |  |  | // 	])
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will forget repeating items...
 | 
					
						
							|  |  |  | // NOTE: normalize will slow things down...
 | 
					
						
							|  |  |  | Array.prototype.toMap = function(normalize){ | 
					
						
							|  |  |  | 	return normalize ?  | 
					
						
							|  |  |  | 		this | 
					
						
							|  |  |  | 			.reduce(function(m, e, i){ | 
					
						
							|  |  |  | 				m.set(normalize(e), i) | 
					
						
							|  |  |  | 				return m }, new Map()) | 
					
						
							|  |  |  | 		: this | 
					
						
							|  |  |  | 			.reduce(function(m, e, i){ | 
					
						
							|  |  |  | 				m.set(e, i) | 
					
						
							|  |  |  | 				return m }, new Map()) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 03:12:42 +03:00
										 |  |  | // 	zip(array, array, ...)
 | 
					
						
							|  |  |  | // 		-> [[item, item, ...], ...]
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	zip(func, array, array, ...)
 | 
					
						
							|  |  |  | // 		-> [func(i, [item, item, ...]), ...]
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | Array.zip =  | 
					
						
							|  |  |  | function(func, ...arrays){ | 
					
						
							|  |  |  | 	var i = arrays[0] instanceof Array ?  | 
					
						
							|  |  |  | 		0  | 
					
						
							|  |  |  | 		: arrays.shift() | 
					
						
							|  |  |  | 	if(func instanceof Array){ | 
					
						
							|  |  |  | 		arrays.splice(0, 0, func) | 
					
						
							|  |  |  | 		func = null } | 
					
						
							|  |  |  | 	// build the zip item...
 | 
					
						
							|  |  |  | 	// NOTE: this is done this way to preserve array sparseness...
 | 
					
						
							|  |  |  | 	var s = arrays | 
					
						
							| 
									
										
										
										
											2020-10-16 02:02:21 +03:00
										 |  |  | 		.reduce( | 
					
						
							|  |  |  | 			function(res, a, j){ | 
					
						
							|  |  |  | 				//a.length > i
 | 
					
						
							|  |  |  | 				i in a | 
					
						
							|  |  |  | 					&& (res[j] = a[i]) | 
					
						
							|  |  |  | 				return res },  | 
					
						
							|  |  |  | 			new Array(arrays.length)) | 
					
						
							| 
									
										
										
										
											2020-10-15 03:12:42 +03:00
										 |  |  | 	return arrays | 
					
						
							|  |  |  | 			// check that at least one array is longer than i...
 | 
					
						
							|  |  |  | 			.reduce(function(res, a){  | 
					
						
							|  |  |  | 				return Math.max(res, i, a.length) }, 0) > i ? | 
					
						
							|  |  |  | 		// collect zip item...
 | 
					
						
							|  |  |  | 		[func ? func(i, s) : s] | 
					
						
							|  |  |  | 			// get next...
 | 
					
						
							|  |  |  | 			.concat(this.zip(func, i+1, ...arrays)) | 
					
						
							|  |  |  | 		// done...
 | 
					
						
							|  |  |  | 		: [] } | 
					
						
							|  |  |  | // XXX would be nice for this to use the instance .zip(..) in recursion...
 | 
					
						
							|  |  |  | // 		...this might be done by reversign the current implementation, i.e.
 | 
					
						
							|  |  |  | // 		for instance .zip(..) to be the main implementation and for 
 | 
					
						
							|  |  |  | // 		Array.zip(..) to be a proxy to that...
 | 
					
						
							|  |  |  | Array.prototype.zip = | 
					
						
							|  |  |  | function(func, ...arrays){ | 
					
						
							|  |  |  | 	return func instanceof Array ? | 
					
						
							|  |  |  | 		this.constructor.zip(this, func, ...arrays) | 
					
						
							|  |  |  | 		: this.constructor.zip(func, this, ...arrays) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 06:59:56 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	Array.iter()
 | 
					
						
							|  |  |  | //	Array.iter([ .. ])
 | 
					
						
							|  |  |  | //		-> iterator
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	array.iter()
 | 
					
						
							|  |  |  | //		-> iterator
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-11-10 01:58:51 +03:00
										 |  |  | // XXX should this take an argument and be like map??
 | 
					
						
							| 
									
										
										
										
											2020-11-18 06:59:56 +03:00
										 |  |  | Array.prototype.iter =  | 
					
						
							|  |  |  | 	function*(){ | 
					
						
							|  |  |  | 		for(var e of this){ | 
					
						
							|  |  |  | 			yield e } } | 
					
						
							|  |  |  | Array.iter = | 
					
						
							|  |  |  | 	function*(lst=[]){ | 
					
						
							|  |  |  | 		yield* lst.iter() } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 06:22:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 02:02:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 04:40:16 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |