<commit_before>Class("obsjs.arrayBase", function () {
    
    function dictionary () {
        this.__keyArray = [], this.__valueArray = [];        
    }
    
    dictionary.prototype.add = function (key, value) {
        var i = this.__keyArray.indexOf(key);
        i === -1 ? (this.__keyArray.push(key), this.__valueArray.push(value)) : this.__valueArray[i] = value;

        return value;
    };
    
    dictionary.prototype.clear = function () {
        this.__keyArray.length = 0;
        this.__valueArray.length = 0;        
    };
    
    dictionary.prototype.remove = function (key) {
        var i = this.__keyArray.indexOf(key);
        if (i !== -1) {
            this.__keyArray.splice(i, 0);
            this.__valueArray.splice(i, 0);
            return true;
        }            

        return false;
    };
    
    dictionary.prototype.value = function (key) {
        return this.__valueArray[this.__keyArray.indexOf(key)];
    };
    
    var arrayBase = objjs.object.extend.call(Array, function arrayBase (initialValues) {
        
        Array.call(this);
        
        if (arguments.length)
            if (!(arguments[0] instanceof Array))
                throw "The initial values must be an array";
        
        this.$disposables = [];
        this.$boundArrays = new dictionary();
        this.$callbacks = [];
        this.$changeBatch = [];
        this.$length = initialValues ? initialValues.length : 0;    
        
        if (initialValues)
            for(var i = 0, ii = initialValues.length; i < ii; i++)
                this[i] = initialValues[i]; // doing it this way as it will not publish changes
    });
    
    arrayBase.prototype._super = objjs.object.prototype._super;
    arrayBase.extend = objjs.object.extend;
    
    arrayBase.isValidArrayChange = function (change) {
        return change.type === "splice" || !isNaN(parseInt(change.name));
    };
    
    arrayBase.prototype.captureChanges = function (logic, callback) {
        throw "Abstract methods must be overridden";
    };
         
    arrayBase.prototype.onNextArrayChange = function (callback) {
        
        throw "Abstract methods must be implemented";
    };
         
    arrayBase.prototype.processChangeBatch = function () {
        
        var changeBatch = this.$changeBatch.slice();
        this.$changeBatch.length = 0;

        obsjs.utils.observeCycleHandler.instance.execute(this, (function () {
        	enumerateArr(obsjs.observableBase.processChanges(this.$callbacks, changeBatch), function (c) { c(); });
		}).bind(this));
    };
    
    arrayBase.prototype.registerChangeBatch = function (changes) {
        
        // not interested in property changes
        for (var i = changes.length - 1; i >= 0; i--)
            if (!arrayBase.isValidArrayChange(changes[i]))
                changes.splice(i, 1);
        
        return obsjs.observableBase.prototype.registerChangeBatch.call(this, changes);
    };
            
    function changeIndex(index) {
        if (typeof index === "number" && index % 1 === 0) {
            return index;
        } else if (index === null) {
            return 0;
        } else if (typeof index === "boolean") {
            return index ? 1 : 0;
        } else if (typeof index === "string" && !isNaN(index = parseFloat(index)) && index % 1 === 0) {
            return index;
        }

        return undefined;
    }

    Object.defineProperty(arrayBase.prototype, "length", {
        set: function(v) {
            if ((v = changeIndex(v)) === undefined) 
                throw RangeError("Invalid array length");

            if (v === this.$length)
                return;

            if(!this.__alteringArray) {
                if(v > this.$length) {
                    var args = new Array(v - this.length + 2);
                    args[0] = this.length;
                    args[1] = 0;
                    this.splice.apply(this, args);
                } else if(v < this.$length) {
                    this.splice(v, this.length - v);
                }
            }
            
            var oldValue = this.$length;
            this.$length = v;
        },
        get: function() {
            return this.$length;
        }
    });

    arrayBase.prototype._init = function () {
        throw "Abstract methods must be implemented";
    };
    
    arrayBase.prototype.observe = function (callback, context, options) {
        // options evaluateOnEachChange and useRawChanges
		
        if (typeof arguments[0] === "string") {			
            var args = Array.prototype.slice.call(arguments);
            args.splice(0, 0, this);
            return obsjs.observe.apply(null, args);
        }
		
		return this.addCallback(new obsjs.callbacks.arrayCallback(callback, context, options));
    };
	
	arrayBase.prototype.disposableFor = function (changeCallback) {
		var dispose = {
			dispose: (function (allowPendingChanges) {

				if (!dispose) return;
				dispose = null;

				if (allowPendingChanges)
					this.onNextArrayChange(function (change) {
						changeCallback.deactivate(change);
					});
				else
					changeCallback.deactivate();
			}).bind(this)
		};
		
		return dispose;
	};
    
    arrayBase.prototype.alteringArray = function(method, arguments) {
        if (this.__alteringArray) {
            return Array.prototype[method].apply(this, arguments);
        } else {
            try {
                this.__alteringArray = true;
            	return Array.prototype[method].apply(this, arguments);
            } finally {
                this.__alteringArray = false;
            }
        }
    };

    arrayBase.copyAll = function (from, to, convert) {
        
        var args;
        if (convert) {
            args = [];
            enumerateArr(from, function (item) {
                args.push(convert(item));
            });
        } else {
            args = from.slice();
        }
        
        args.splice(0, 0, 0, to.length);
        to.splice.apply(to, args);
    };
    
    arrayBase.prototype.bind = function(anotherArray) {
        
        if (this.$boundArrays.value(anotherArray)) return;        
        
        if (!(anotherArray instanceof obsjs.array && anotherArray.$boundArrays.value(this)))
            arrayBase.copyAll(this, anotherArray);
        
        this.$boundArrays.add(anotherArray, {});
        
		return this.addCallback(new obsjs.callbacks.boundArrayCallback(this, anotherArray));
    };
	
	arrayBase.prototype.addCallback = function (callback) {
        this._init();

        this.$callbacks.push(callback);

        this.onNextArrayChange(function (change) {
            callback.activate(change);
        });
        
        var dispose = this.disposableFor(callback);
        
        this.$disposables.push(dispose);
        
        return dispose;
	};
    
    arrayBase.prototype.dispose = function() {
        
        enumerateArr(this.$disposables, function (d) {
            d.dispose();
        });
        
        this.$disposables.length = 0;        
        this.$boundArrays.clear();
        this.$callbacks.length = 0;
    };
    
    return arrayBase;
});<commit_msg>testing<commit_after>Class("obsjs.arrayBase", function () {
        
    var arrayBase = objjs.object.extend.call(Array, function arrayBase (initialValues) {
        
        Array.call(this);
        
        if (arguments.length)
            if (!(arguments[0] instanceof Array))
                throw "The initial values must be an array";
        
        this.$disposables = [];
        this.$boundArrays = [];
        this.$callbacks = [];
        this.$changeBatch = [];
        this.$length = initialValues ? initialValues.length : 0;    
        
        if (initialValues)
            for(var i = 0, ii = initialValues.length; i < ii; i++)
                this[i] = initialValues[i]; // doing it this way as it will not publish changes
    });
    
    arrayBase.prototype._super = objjs.object.prototype._super;
    arrayBase.extend = objjs.object.extend;
    
    arrayBase.isValidArrayChange = function (change) {
        return change.type === "splice" || !isNaN(parseInt(change.name));
    };
    
    arrayBase.prototype.captureChanges = function (logic, callback) {
        throw "Abstract methods must be overridden";
    };
         
    arrayBase.prototype.onNextArrayChange = function (callback) {
        
        throw "Abstract methods must be implemented";
    };
         
    arrayBase.prototype.processChangeBatch = function () {
        
        var changeBatch = this.$changeBatch.slice();
        this.$changeBatch.length = 0;

        obsjs.utils.observeCycleHandler.instance.execute(this, (function () {
        	enumerateArr(obsjs.observableBase.processChanges(this.$callbacks, changeBatch), function (c) { c(); });
		}).bind(this));
    };
    
    arrayBase.prototype.registerChangeBatch = function (changes) {
        
        // not interested in property changes
        for (var i = changes.length - 1; i >= 0; i--)
            if (!arrayBase.isValidArrayChange(changes[i]))
                changes.splice(i, 1);
        
        return obsjs.observableBase.prototype.registerChangeBatch.call(this, changes);
    };
            
    function changeIndex(index) {
        if (typeof index === "number" && index % 1 === 0) {
            return index;
        } else if (index === null) {
            return 0;
        } else if (typeof index === "boolean") {
            return index ? 1 : 0;
        } else if (typeof index === "string" && !isNaN(index = parseFloat(index)) && index % 1 === 0) {
            return index;
        }

        return undefined;
    }

    Object.defineProperty(arrayBase.prototype, "length", {
        set: function(v) {
            if ((v = changeIndex(v)) === undefined) 
                throw RangeError("Invalid array length");

            if (v === this.$length)
                return;

            if(!this.__alteringArray) {
                if(v > this.$length) {
                    var args = new Array(v - this.length + 2);
                    args[0] = this.length;
                    args[1] = 0;
                    this.splice.apply(this, args);
                } else if(v < this.$length) {
                    this.splice(v, this.length - v);
                }
            }
            
            var oldValue = this.$length;
            this.$length = v;
        },
        get: function() {
            return this.$length;
        }
    });

    arrayBase.prototype._init = function () {
        throw "Abstract methods must be implemented";
    };
    
    arrayBase.prototype.observe = function (callback, context, options) {
        // options evaluateOnEachChange and useRawChanges
		
        if (typeof arguments[0] === "string") {			
            var args = Array.prototype.slice.call(arguments);
            args.splice(0, 0, this);
            return obsjs.observe.apply(null, args);
        }
		
		return this.addCallback(new obsjs.callbacks.arrayCallback(callback, context, options));
    };
	
	arrayBase.prototype.disposableFor = function (changeCallback) {
		var dispose = {
			dispose: (function (allowPendingChanges) {

				if (!dispose) return;
				dispose = null;

				if (allowPendingChanges)
					this.onNextArrayChange(function (change) {
						changeCallback.deactivate(change);
					});
				else
					changeCallback.deactivate();
			}).bind(this)
		};
		
		return dispose;
	};
    
    arrayBase.prototype.alteringArray = function(method, arguments) {
		
		if (this.__alteringArray) {
            return Array.prototype[method].apply(this, arguments);
        } else {
            try {
                this.__alteringArray = true;
            	return Array.prototype[method].apply(this, arguments);
            } finally {
                this.__alteringArray = false;
            }
        }
    };

    arrayBase.copyAll = function (from, to, convert) {
        
        var args;
        if (convert) {
            args = [];
            enumerateArr(from, function (item) {
                args.push(convert(item));
            });
        } else {
            args = from.slice();
        }
        
        args.splice(0, 0, 0, to.length);
        to.splice.apply(to, args);
    };
    
    arrayBase.prototype.bind = function(anotherArray) {
        
        if (!anotherArray || this.$boundArrays.indexOf(anotherArray) !== -1) return;
		
		this.$boundArrays.push(anotherArray);
        
        if (!(anotherArray instanceof obsjs.array) || anotherArray.$boundArrays.indexOf(this) === -1)
            arrayBase.copyAll(this, anotherArray);
		
		return new obsjs.disposable(function () {
			if (!anotherArray) return;
			var i;
			if ((i = this.$boundArrays.indexOf(anotherArray)) !== -1)
				this.$boundArrays.splice(i, 1);
			
			anotherArray = null;
		});
    };
	
	arrayBase.prototype.addCallback = function (callback) {
        this._init();

        this.$callbacks.push(callback);

        this.onNextArrayChange(function (change) {
            callback.activate(change);
        });
        
        var dispose = this.disposableFor(callback);
        
        this.$disposables.push(dispose);
        
        return dispose;
	};
    
    arrayBase.prototype.dispose = function() {
        
        enumerateArr(this.$disposables, function (d) {
            d.dispose();
        });
        
        this.$disposables.length = 0;        
        this.$boundArrays.length = 0;
        this.$callbacks.length = 0;
    };
    
    return arrayBase;
});
{'fraction_non_alphanumeric': 0.12311780336581045, 'fraction_numerical': 0.004650132860938884, 'mean_word_length': 1.8098299460804645, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '3693664', 'n_tokens_mistral': 3916, 'n_tokens_neox': 3675, 'n_words': 765}