<commit_before>var NOTSET = {};

ReactiveObj = function (initialValue, options) {
  var self = this;
  self._obj = typeof initialValue === 'object' ? initialValue : {};
  self._deps = {children: {}, deps: {}};
  self._willInvalidate = [];
  self._willCleanDeps = [];

  if (!options) return;
  if (typeof options.transform === 'function')
    self._transform = options.transform;
};
_.extend(ReactiveObj.prototype, {

  // Returns a normalized keyPath or throws an error if it is invalid
  _matchKeyPath: function (keyPath) {
    if (typeof keyPath === 'string') keyPath = [keyPath];
    else if (typeof keyPath === 'undefined') keyPath = [];
    else if (!(keyPath instanceof Array)) throw new Error('Invalid keypath');

    return keyPath;
  },

  // Visits a path in object and calls the given `visitor` callback
  // Returns NOTSET if path does not exist
  _visitPath: function (node, keyPath, visitor) {
    for (var i=0, l=keyPath.length, s=node, lastS=null; i<l; i+=1) {
      if (typeof s === 'object' && keyPath[i] in s) {
        lastS = s;
        s = s[keyPath[i]];
      }
      else break;
    }
    if (i === l || !keyPath.length)
      return typeof visitor !== 'function' ? s : visitor({
        node: lastS,
        value: s,
        key: keyPath[i - 1]
      });

    return NOTSET;
  },

  // Shallow clone an object with new value at the path
  _copyOnWrite: function (node, path, value) {
    var prevNode = node;
    var newNode = {};
    var currentNode = newNode;
    var currentKey, currentValue;

    for (var i=0, l=path.length-1; i<=l; i+=1) {
      currentKey = path[i];
      if (i === l) currentValue = value;
      else {
        if (prevNode[currentKey] instanceof Array) currentValue = [];
        else currentValue = {};
      }

      if (prevNode) _.extend(currentNode, _.omit(prevNode, currentKey));

      currentNode[currentKey] = currentValue;
      currentNode = currentNode[currentKey];
      if (prevNode) prevNode = prevNode[currentKey];
    }

    return newNode;
  },

  // Add a dependency
  _addDep: function (opt) {
    var self = this;
    var currentNode = self._deps;
    var nextNode;

    if (!opt.path.length) self._addDepToNode(self._deps, opt);

    for (var i=0, l=opt.path.length-1; i<=l; i+=1) {
      nextNode = currentNode.children[opt.path[i]] =
        currentNode.children[opt.path[i]] ||
        {children: {}, deps: {}};

      if (i === l) self._addDepToNode(nextNode, opt);

      currentNode = nextNode;
    }
  },

  _addDepToNode: function (node, opt) {
    node.deps[opt.id] = {
      comp: opt.comp,
      lastVal: opt.lastVal
    };
  },

  // Remove a dependency
  _removeDep: function (opt) {
    var self = this;
    var currentNode = self._deps;
    var nextNode;

    if (!opt.path.length) self._removeDepFromNode(self._deps, opt);

    for (var i=0, l=opt.path.length-1; i<=l; i+=1) {
      if (!currentNode) break;
      nextNode = currentNode.children[opt.path[i]];

      if (i === l) self._removeDepFromNode(nextNode, opt);

      currentNode = nextNode;
    }
  },

  _removeDepFromNode: function (node, opt) {
    var self = this;
    if (!node.deps[opt.id]) return;

    delete node.deps[opt.id];<commit_msg>Update _addDepToNode to handle 'equals' option<commit_after>var NOTSET = {};

ReactiveObj = function (initialValue, options) {
  var self = this;
  self._obj = typeof initialValue === 'object' ? initialValue : {};
  self._deps = {children: {}, deps: {}};
  self._willInvalidate = [];
  self._willCleanDeps = [];

  if (!options) return;
  if (typeof options.transform === 'function')
    self._transform = options.transform;
};
_.extend(ReactiveObj.prototype, {

  // Returns a normalized keyPath or throws an error if it is invalid
  _matchKeyPath: function (keyPath) {
    if (typeof keyPath === 'string') keyPath = [keyPath];
    else if (typeof keyPath === 'undefined') keyPath = [];
    else if (!(keyPath instanceof Array)) throw new Error('Invalid keypath');

    return keyPath;
  },

  // Visits a path in object and calls the given `visitor` callback
  // Returns NOTSET if path does not exist
  _visitPath: function (node, keyPath, visitor) {
    for (var i=0, l=keyPath.length, s=node, lastS=null; i<l; i+=1) {
      if (typeof s === 'object' && keyPath[i] in s) {
        lastS = s;
        s = s[keyPath[i]];
      }
      else break;
    }
    if (i === l || !keyPath.length)
      return typeof visitor !== 'function' ? s : visitor({
        node: lastS,
        value: s,
        key: keyPath[i - 1]
      });

    return NOTSET;
  },

  // Shallow clone an object with new value at the path
  _copyOnWrite: function (node, path, value) {
    var prevNode = node;
    var newNode = {};
    var currentNode = newNode;
    var currentKey, currentValue;

    for (var i=0, l=path.length-1; i<=l; i+=1) {
      currentKey = path[i];
      if (i === l) currentValue = value;
      else {
        if (prevNode[currentKey] instanceof Array) currentValue = [];
        else currentValue = {};
      }

      if (prevNode) _.extend(currentNode, _.omit(prevNode, currentKey));

      currentNode[currentKey] = currentValue;
      currentNode = currentNode[currentKey];
      if (prevNode) prevNode = prevNode[currentKey];
    }

    return newNode;
  },

  // Add a dependency
  _addDep: function (opt) {
    var self = this;
    var currentNode = self._deps;
    var nextNode;

    if (!opt.path.length) self._addDepToNode(self._deps, opt);

    for (var i=0, l=opt.path.length-1; i<=l; i+=1) {
      nextNode = currentNode.children[opt.path[i]] =
        currentNode.children[opt.path[i]] ||
        {children: {}, deps: {}};

      if (i === l) self._addDepToNode(nextNode, opt);

      currentNode = nextNode;
    }
  },

  _addDepToNode: function (node, opt) {
    node.deps[opt.id] = {
      comp: opt.comp,
      lastVal: opt.lastVal
    };
    if ('equals' in opt) node.deps[opt.id].equals = opt.equals;
  },

  // Remove a dependency
  _removeDep: function (opt) {
    var self = this;
    var currentNode = self._deps;
    var nextNode;

    if (!opt.path.length) self._removeDepFromNode(self._deps, opt);

    for (var i=0, l=opt.path.length-1; i<=l; i+=1) {
      if (!currentNode) break;
      nextNode = currentNode.children[opt.path[i]];

      if (i === l) self._removeDepFromNode(nextNode, opt);

      currentNode = nextNode;
    }
  },

  _removeDepFromNode: function (node, opt) {
    var self = this;
    if (!node.deps[opt.id]) return;

    delete node.deps[opt.id];
{'fraction_non_alphanumeric': 0.14538734021253658, 'fraction_numerical': 0.003696288310488218, 'mean_word_length': 2.7472590882862087, 'pattern_counts': {'":': 0, '<': 11, '<?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': '1645644', 'n_tokens_mistral': 2192, 'n_tokens_neox': 2135, 'n_words': 580}