<commit_before>var bind = require('lodash.bind');
var difference = require('lodash.difference');
var each = require('lodash.foreach');
var isRegExp = require('lodash.isregexp');
var keys = require('lodash.keys');
var map = require('lodash.map');
var object = require('lodash.zipobject');
var omit = require('lodash.omit');
var partial = require('lodash.partial');
var where = require('lodash.where');

var utils = require('./utils');

exports._getEventBubblingHandler = function (_super, propertyName) {
    var superBubbler;
    if (!this[propertyName].isCollection) superBubbler = _super.prototype._getEventBubblingHandler.call(this, propertyName);
    return bind(function (name, model, newValue, op) {
        var config = this._patcherConfig;
        if (superBubbler) superBubbler(name, model, newValue);
        var collection, index, opArgs, ignorePaths, ignoreLength, ignoreTest;
        if (name.indexOf('patcher:') !== -1 && op) {
            if ((ignorePaths = config.ignorePaths) && (ignoreLength = ignorePaths.length)) {
                for (var i=0; i<ignoreLength; i++) {
                    ignoreTest = ignorePaths[i];
                    if (typeof ignoreTest === 'string' && ignoreTest.indexOf(op.path) !== -1) {
                        return;
                    }
                    if (typeof ignoreTest === 'function' && !ignoreTest(op.path)) {
                        return;
                    }
                    if (isRegExp(ignoreTest) && ignoreTest.test(op.path)) {
                        return;
                    }
                }
            }
            collection = this[propertyName].isCollection ? this[propertyName] : null;
            child = this[propertyName].isState ? this[propertyName] : null;
            if (op.op === 'remove' || name.indexOf('op-removed') !== -1) {
                var ops = this._getOps();
                var removeOps = where(ops, {cid: op.cid});
                this._setOps(difference(ops, removeOps));
                each(removeOps, function(op) {
                    this.trigger('patcher:op-removed', model, 1, op);
                }, this);
            }
            if (collection) {
                index = this._modelIndex(model, propertyName);
                if (model.isNew() && ['add', 'replace'].indexOf(op.op) !== -1) {
                    opArgs = ['add', utils.makePath(propertyName, '-'), model.serialize()];
                } else {
                    opArgs = [op.op, utils.makePath(propertyName, (index === -1 ? collection.indexOf(model) : index), op.path)];
                    if (op.value) opArgs.push(op.value);
                }
            }
            if (child) {
                if (model.isNew() && ['add', 'replace'].indexOf(op.op) !== -1) {
                    opArgs = ['add', utils.makePath(propertyName), model.serialize()];
                } else {
                    opArgs = [op.op, utils.makePath(propertyName, op.path), (op.op === 'remove' ? op.value : op.cid)];
                    if (op.value) opArgs.push(op.value);
                }
            }
            
            if (opArgs) {
                opArgs.push(op.cid);
                return this._queueOp.apply(this, opArgs);
            }
            this.trigger.apply(this, arguments);
        }
    }, this);
};

exports._initCollections = function (_super) {
    _super.prototype._initCollections.call(this);
    var coll;
    for (coll in this._collections) {
        this.listenTo(this[coll], 'all', this._getEventBubblingHandler(coll));
    }
};

exports.parse = function (_super, response, options) {
    options = options || {};
    var parsed = _super.prototype.parse.call(this, response, options);
    if (parsed && options && options.parse === true && !options._patcherParsed) {
        this[this._patcherConfig.originalProperty] = parsed;
        options._patcherParsed = true;
    }
    return parsed;
};

exports.save = function (_super, key, val, options) {
    // If root model is new, we save normally
    if (this.isNew()) {
        return _super.prototype.save.apply(this, arguments);
    }
    if (this._blockSave) return;
    // Mimic the barebones of Backbone.Model.prototype.save's argument handling
    var attrs;
    if (key == null || typeof key === 'object') {
        attrs = key;
        options = val;
    } else {
        (attrs = {})[key] = val;
    }
    // If attrs have been passed, but are invalid, abort.
    if (attrs && !this.set(attrs, options)) return false;
    // Abort if there are no ops to send
    if (!this._getOps().length) return;
    if (!options) options = {};
    options.attrs = map(this._ops, function (op) {
        return omit(op, 'cid');
    });
    var model = this;
    // Since we've bypassed the usual save process, we need to trigger 'sync' ourselves
    var success = options.success;
    options.success = function (resp) {
        model._blockSave = false;
        // TODO: make this handle recursive ops
        if (model._resetOps) model._resetOps();
        if (success) success(model, resp, options);
        model.trigger('sync', model, resp, options);
    };
    // In case of error, we need to unblock saving.
    var error = options.error;
    options.error = function (xhr, status, msg) {
        model._blockSave = false;
        if (error) error(xhr, status, msg);
    };<commit_msg>follow &-model's save behavior for set on success<commit_after>var bind = require('lodash.bind');
var difference = require('lodash.difference');
var each = require('lodash.foreach');
var isObject = require('lodash.isobject');
var isRegExp = require('lodash.isregexp');
var keys = require('lodash.keys');
var map = require('lodash.map');
var object = require('lodash.zipobject');
var omit = require('lodash.omit');
var partial = require('lodash.partial');
var where = require('lodash.where');

var utils = require('./utils');

exports._getEventBubblingHandler = function (_super, propertyName) {
    var superBubbler;
    if (!this[propertyName].isCollection) superBubbler = _super.prototype._getEventBubblingHandler.call(this, propertyName);
    return bind(function (name, model, newValue, op) {
        var config = this._patcherConfig;
        if (superBubbler) superBubbler(name, model, newValue);
        var collection, index, opArgs, ignorePaths, ignoreLength, ignoreTest;
        if (name.indexOf('patcher:') !== -1 && op) {
            if ((ignorePaths = config.ignorePaths) && (ignoreLength = ignorePaths.length)) {
                for (var i=0; i<ignoreLength; i++) {
                    ignoreTest = ignorePaths[i];
                    if (typeof ignoreTest === 'string' && ignoreTest.indexOf(op.path) !== -1) {
                        return;
                    }
                    if (typeof ignoreTest === 'function' && !ignoreTest(op.path)) {
                        return;
                    }
                    if (isRegExp(ignoreTest) && ignoreTest.test(op.path)) {
                        return;
                    }
                }
            }
            collection = this[propertyName].isCollection ? this[propertyName] : null;
            child = this[propertyName].isState ? this[propertyName] : null;
            if (op.op === 'remove' || name.indexOf('op-removed') !== -1) {
                var ops = this._getOps();
                var removeOps = where(ops, {cid: op.cid});
                this._setOps(difference(ops, removeOps));
                each(removeOps, function(op) {
                    this.trigger('patcher:op-removed', model, 1, op);
                }, this);
            }
            if (collection) {
                index = this._modelIndex(model, propertyName);
                if (model.isNew() && ['add', 'replace'].indexOf(op.op) !== -1) {
                    opArgs = ['add', utils.makePath(propertyName, '-'), model.serialize()];
                } else {
                    opArgs = [op.op, utils.makePath(propertyName, (index === -1 ? collection.indexOf(model) : index), op.path)];
                    if (op.value) opArgs.push(op.value);
                }
            }
            if (child) {
                if (model.isNew() && ['add', 'replace'].indexOf(op.op) !== -1) {
                    opArgs = ['add', utils.makePath(propertyName), model.serialize()];
                } else {
                    opArgs = [op.op, utils.makePath(propertyName, op.path), (op.op === 'remove' ? op.value : op.cid)];
                    if (op.value) opArgs.push(op.value);
                }
            }
            
            if (opArgs) {
                opArgs.push(op.cid);
                return this._queueOp.apply(this, opArgs);
            }
            this.trigger.apply(this, arguments);
        }
    }, this);
};

exports._initCollections = function (_super) {
    _super.prototype._initCollections.call(this);
    var coll;
    for (coll in this._collections) {
        this.listenTo(this[coll], 'all', this._getEventBubblingHandler(coll));
    }
};

exports.parse = function (_super, response, options) {
    options = options || {};
    var parsed = _super.prototype.parse.call(this, response, options);
    if (parsed && options && options.parse === true && !options._patcherParsed) {
        this[this._patcherConfig.originalProperty] = parsed;
        options._patcherParsed = true;
    }
    return parsed;
};

exports.save = function (_super, key, val, options) {
    // If root model is new, we save normally
    if (this.isNew()) {
        return _super.prototype.save.apply(this, arguments);
    }
    if (this._blockSave) return;
    // Mimic the barebones of Backbone.Model.prototype.save's argument handling
    var attrs;
    if (key == null || typeof key === 'object') {
        attrs = key;
        options = val;
    } else {
        (attrs = {})[key] = val;
    }
    // If attrs have been passed, but are invalid, abort.
    if (attrs && !this.set(attrs, options)) return false;
    // Abort if there are no ops to send
    if (!this._getOps().length) return;
    if (!options) options = {};
    options.attrs = map(this._ops, function (op) {
        return omit(op, 'cid');
    });
    var model = this;
    if (options.parse === void 0) options.parse = true;
    // Since we've bypassed the usual save process, we need to trigger 'sync' ourselves
    var success = options.success;
    options.success = function (resp) {
        model._blockSave = false;
        // TODO: make this handle recursive ops
        if (model._resetOps) model._resetOps();
        var serverAttrs = resp && model.parse(resp, options);
        if (isObject(serverAttrs) && !model.set(serverAttrs, options)) {
            return false;
        }
        if (success) success(model, resp, options);
        model.trigger('sync', model, resp, options);
    };
    // In case of error, we need to unblock saving.
    var error = options.error;
    options.error = function (xhr, status, msg) {
        model._blockSave = false;
        if (error) error(xhr, status, msg);
    };
{'fraction_non_alphanumeric': 0.14105129137868316, 'fraction_numerical': 0.0015460167333575846, 'mean_word_length': 2.087310499719259, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '6308650', 'n_tokens_mistral': 3173, 'n_tokens_neox': 3077, 'n_words': 767}