<commit_before>function pathify(p) {
  if (Array.isArray(p)) p = p.join('.');
  return '$$_' + p; // prepend special symbols to avoid name conflict with protos
}
class ListenTree {
  constructor() {
    this._listeners = [];
    this._count = 1;
    this._listened = {};
  }

  on(p, listener) {
    const path = pathify(p);
    if (!listener.$id) {
      listener.$id = this._count++;
    }
    const key = path + '//' + listener.$id;
    if (this._listened[key]) return;
    if (!this._listeners[path]) this._listeners[path] = [];
    this._listeners[path].push(listener);
    this._listened[key] = true; 
  }

  off(p, listener) {
    const path = pathify(p);
    const listeners = this._listeners[path];
    if (!listeners || !listeners.length) return;
    listeners.splice(listeners.indexOf(listener), 1);
  }

  emit(p) {
    const path = pathify(p);
    const listeners = {};
    Object.keys(this._listeners).forEach(p2 => {
      if (p2.indexOf(path) !== 0 && path.indexOf(p2) !== 0) return;
      (this._listeners[p2] || []).forEach(listener => {
        listeners[listener.$id] = listener;
      });
    });
    Object.keys(listeners).forEach(k => listeners[k]());
  }
}

module.exports = ListenTree;
<commit_msg>off should set the key false<commit_after>function pathify(p) {
  if (Array.isArray(p)) p = p.join('.');
  return '$$_' + p; // prepend special symbols to avoid name conflict with protos
}
function keyify(path, listener) {
  return path + '//' + listener.$id;
}
class ListenTree {
  constructor() {
    this._listeners = [];
    this._count = 1;
    this._listened = {};
  }

  on(p, listener) {
    const path = pathify(p);
    if (!listener.$id) {
      listener.$id = this._count++;
    }
    const key = keyify(path, listener.$id);
    if (this._listened[key]) return;
    if (!this._listeners[path]) this._listeners[path] = [];
    this._listeners[path].push(listener);
    this._listened[key] = true; 
  }

  off(p, listener) {
    const path = pathify(p);
    const listeners = this._listeners[path];
    if (!listeners || !listeners.length) return;
    listeners.splice(listeners.indexOf(listener), 1);
    this._listened[keyify(path, listener)] = false; 
  }

  emit(p) {
    const path = pathify(p);
    const listeners = {};
    Object.keys(this._listeners).forEach(p2 => {
      if (p2.indexOf(path) !== 0 && path.indexOf(p2) !== 0) return;
      (this._listeners[p2] || []).forEach(listener => {
        listeners[listener.$id] = listener;
      });
    });
    Object.keys(listeners).forEach(k => listeners[k]());
  }
}

module.exports = ListenTree;

{'fraction_non_alphanumeric': 0.17819868573637418, 'fraction_numerical': 0.006184770003865481, 'mean_word_length': 3.0755905511811026, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '3689481', 'n_tokens_mistral': 884, 'n_tokens_neox': 874, 'n_words': 176}