<commit_before>define([
	"dojo/_base/lang",
	"dojo/_base/declare",
	"dojo/aspect",
	"dojo/when",
	"dojo/promise/all",
	"dojo/_base/array"
	/*=====, "./api/Store" =====*/
], function(lang, declare, aspect, when, whenAll, arrayUtil /*=====, Store =====*/){

// module:
//		dstore/Observable
var undef, revision = 0;

	function createRange(newStart, newEnd){
		return {
			start: newStart,
			count: newEnd - newStart
		};
	}

	function registerRange(ranges, newStart, newEnd){
		for(var i = ranges.length - 1; i >= 0; --i){
			var existingRange = ranges[i],
				existingStart = existingRange.start,
				existingEnd = existingStart + existingRange.count;

			if (newStart > existingEnd){
				// existing range completely precedes new range. we are done.
				ranges.splice(i + 1, 0, createRange(newStart, newEnd));
				return;
			}else if(newEnd >= existingStart){
				// the ranges overlap and must be merged into a single range
				newStart = Math.min(newStart, existingStart);
				newEnd = Math.max(newEnd, existingEnd);
				ranges.splice(i, 1);
			}
		}

		ranges.unshift(createRange(newStart, newEnd));
	}

	function unregisterRange(ranges, start, end){
		for(var i = 0, range; (range = ranges[i]); ++i){
			var existingStart = range.start,
				existingEnd = existingStart + range.count;

			if(start <= existingStart){
				if(end >= existingEnd){
					// The existing range is within the forgotten range
					ranges.splice(i, 1);
				}else{
					// The forgotten range overlaps the beginning of the existing range
					range.start = end;
					range.count = existingEnd - range.start;

					// Since the forgotten range ends before the existing range,
					// there are no more ranges to update, and we are done
					return;
				}
			}else if(start < existingEnd){
				if(end > existingStart){
					// The forgotten range is within the existing range
					ranges.splice(i, 1, createRange(existingStart, start), createRange(end, existingEnd));

					// We are done because the existing range bounded the forgotten range
					return;
				}else{
					// The forgotten range overlaps the end of the existing range
					range.count = start - range.start;
				}
			}
		}
	}

return declare(null, {
	currentRange: [],
	track: function(){
		var store = this.store || this;

		// monitor for updates by listening to these methods
		var handles = [];
		var eventTypes = {add: 1, update: 1, remove: 1};
		// register to listen for updates
		for(var type in eventTypes){
			this.on(type, (function(type){
				return function(event){
					notify(type, event.target || event.id, event);
				};
			})(type));
		}

		var observed = lang.delegate(this, {
			store: store,
			remove: function(){
				while(handles.length > 0){
					handles.pop().remove();
				}

				this.remove = function(){};
			}
		});

		var originalOn = this.on;
		// now setup our own event scope, for tracked events
		observed.on = function(type, listener){
			return type in eventTypes ?
				aspect.after(observed, 'ontracked' + type, listener, true) :
				originalOn.call(observed, type, listener);
		};

		var ranges = [];
		if(this.hasOwnProperty('data')){
			observed.data = this.data.slice(0); // make local copy
			// Treat in-memory data as one range to allow a single code path for all stores
			registerRange(ranges, 0, observed.data.length);

			observed.releaseRange = function(){};
		}else{
			var originalRange = observed.range;
			observed.range = function(start, end){
				// trigger a request
				var rangeCollection = originalRange.apply(this, arguments).fetch(),
					partialData = this.hasOwnProperty('partialData') ? this.partialData : (this.partialData = []);

				// Wait for total in addition to data so updated objects sorted to
				// the end of the list have a known index<commit_msg>Add comma-separated event support to Observable.on<commit_after>define([
	"dojo/_base/lang",
	"dojo/_base/declare",
	"dojo/aspect",
	"dojo/when",
	"dojo/promise/all",
	"dojo/_base/array",
	"dojo/on",
	/*=====, "./api/Store" =====*/
], function(lang, declare, aspect, when, whenAll, arrayUtil, on /*=====, Store =====*/){

// module:
//		dstore/Observable
var undef, revision = 0;

	function createRange(newStart, newEnd){
		return {
			start: newStart,
			count: newEnd - newStart
		};
	}

	function registerRange(ranges, newStart, newEnd){
		for(var i = ranges.length - 1; i >= 0; --i){
			var existingRange = ranges[i],
				existingStart = existingRange.start,
				existingEnd = existingStart + existingRange.count;

			if (newStart > existingEnd){
				// existing range completely precedes new range. we are done.
				ranges.splice(i + 1, 0, createRange(newStart, newEnd));
				return;
			}else if(newEnd >= existingStart){
				// the ranges overlap and must be merged into a single range
				newStart = Math.min(newStart, existingStart);
				newEnd = Math.max(newEnd, existingEnd);
				ranges.splice(i, 1);
			}
		}

		ranges.unshift(createRange(newStart, newEnd));
	}

	function unregisterRange(ranges, start, end){
		for(var i = 0, range; (range = ranges[i]); ++i){
			var existingStart = range.start,
				existingEnd = existingStart + range.count;

			if(start <= existingStart){
				if(end >= existingEnd){
					// The existing range is within the forgotten range
					ranges.splice(i, 1);
				}else{
					// The forgotten range overlaps the beginning of the existing range
					range.start = end;
					range.count = existingEnd - range.start;

					// Since the forgotten range ends before the existing range,
					// there are no more ranges to update, and we are done
					return;
				}
			}else if(start < existingEnd){
				if(end > existingStart){
					// The forgotten range is within the existing range
					ranges.splice(i, 1, createRange(existingStart, start), createRange(end, existingEnd));

					// We are done because the existing range bounded the forgotten range
					return;
				}else{
					// The forgotten range overlaps the end of the existing range
					range.count = start - range.start;
				}
			}
		}
	}

return declare(null, {
	currentRange: [],
	track: function(){
		var store = this.store || this;

		// monitor for updates by listening to these methods
		var handles = [];
		var eventTypes = {add: 1, update: 1, remove: 1};
		// register to listen for updates
		for(var type in eventTypes){
			this.on(type, (function(type){
				return function(event){
					notify(type, event.target || event.id, event);
				};
			})(type));
		}

		var observed = lang.delegate(this, {
			store: store,
			remove: function(){
				while(handles.length > 0){
					handles.pop().remove();
				}

				this.remove = function(){};
			}
		});

		var originalOn = this.on;
		// now setup our own event scope, for tracked events
		observed.on = function(type, listener){
				return on.parse(observed, type, listener, function(target, type){
				return type in eventTypes ?
					aspect.after(observed, 'ontracked' + type, listener, true) :
					originalOn.call(observed, type, listener);
			});
	};

		var ranges = [];
		if(this.hasOwnProperty('data')){
			observed.data = this.data.slice(0); // make local copy
			// Treat in-memory data as one range to allow a single code path for all stores
			registerRange(ranges, 0, observed.data.length);

			observed.releaseRange = function(){};
		}else{
			var originalRange = observed.range;
			observed.range = function(start, end){
				// trigger a request
				var rangeCollection = originalRange.apply(this, arguments).fetch(),
					partialData = this.hasOwnProperty('partialData') ? this.partialData : (this.partialData = []);

				// Wait for total in addition to data so updated objects sorted to
				// the end of the list have a known index
{'fraction_non_alphanumeric': 0.13117746772721345, 'fraction_numerical': 0.003911852914330421, 'mean_word_length': 3.1981390257252325, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2073051', 'n_tokens_mistral': 2834, 'n_tokens_neox': 2309, 'n_words': 722}