<commit_before>"use strict";

function MessageModel(api) {
  this.api_ = api;
}
MessageModel.prototype.newTailInclusive = function(start, cb) {
  return new MessageTail(this, start, true, cb);
};
MessageModel.prototype.newTail = function(start, cb) {
  return new MessageTail(this, start, false, cb);
};
MessageModel.prototype.newReverseTail = function(start, cb) {
  return new MessageReverseTail(this, start, cb);
};
// This function is NOT meant to be that authoritative. It's just
// because some places in the message view would find it handle to be
// able to compare messages to each other and opaque message ids as a
// data model make this difficult.
MessageModel.prototype.compareMessages = function(a, b) {
  return a.receiveTime - b.receiveTime;
};

function MessageTail(model, start, inclusive, cb) {
  this.model_ = model;
  // The last thing we sent.
  this.lastSent_ = start;
  // Whether the request is inclusive.
  this.inclusive_ = inclusive;
  // The number of messages sent total.
  this.messagesSentTotal_ = 0;
  // The number of messages sent since the last new-tail.
  this.messagesSentRecent_ = 0;
  // The number of messages we want ahead of lastSent_.
  this.messagesWanted_ = 0;
  // Callback. null on close.
  this.cb_ = cb;
  // The ID of the tail.
  this.tailId_ = null;
  // The value of the most recent extend-tail message.
  this.lastExtend_ = 0;

  // Hold onto these so we can unregister them.
  this.connectedCb_ = this.onConnect_.bind(this);
  this.disconnectCb_ = this.onDisconnect_.bind(this);
  this.messagesCb_ = this.onMessages_.bind(this);
  this.model_.api_.addEventListener("connect", this.connectedCb_);

  this.onConnect_();
}
MessageTail.prototype.onConnect_ = function() {
  // Unregister our old handlers.
  this.onDisconnect_();
  this.socket_ = this.model_.api_.socket();
  if (this.socket_) {
    this.socket_.addEventListener("messages", this.messagesCb_);
    this.socket_.sockJS().addEventListener("close", this.disconnectCb_);
    // Reset everything.
    this.createTail_();
    this.expandTo(0);
  }
};
MessageTail.prototype.onDisconnect_ = function() {
  if (this.socket_) {
    this.socket_.removeEventListener("messages", this.messagesCb_);
    this.socket_.sockJS().removeEventListener("close", this.disconnectCb_);
    this.socket_ = null;

    // We disconnected. Mark as not the end anymore.
    //
    // TODO(davidben): This makes scrollToEnd reset everything. Maybe
    // add a third "disconnected" state? Would also be good as far as
    // displaying a different message. Could also use API's
    // disconnected event and just leave this one be?
    if (this.cb_)
      this.cb_([], false);
  }
};
MessageTail.prototype.expandTo = function(count) {
  this.messagesWanted_ = Math.max(this.messagesWanted_,
                                  count - this.messagesSentTotal_);
  var newExtend = this.messagesWanted_ + this.messagesSentRecent_;
  if (this.socket_ && this.lastExtend_ < newExtend) {
    this.socket_.send({
      type: "extend-tail",
      id: this.tailId_,
      count:newExtend
    });
    this.lastExtend_ = newExtend;
  }
};
MessageTail.prototype.close = function() {
  if (this.socket_) {
    this.socket_.send({
      type: "close-tail",
      id: this.tailId_
    });
  }
  this.onDisconnect_();
  this.model_.api_.removeEventListener("connect", this.connectedCb_);
  this.cb_ = null;<commit_msg>Don't call this.cb_ after close is called<commit_after>"use strict";

function MessageModel(api) {
  this.api_ = api;
}
MessageModel.prototype.newTailInclusive = function(start, cb) {
  return new MessageTail(this, start, true, cb);
};
MessageModel.prototype.newTail = function(start, cb) {
  return new MessageTail(this, start, false, cb);
};
MessageModel.prototype.newReverseTail = function(start, cb) {
  return new MessageReverseTail(this, start, cb);
};
// This function is NOT meant to be that authoritative. It's just
// because some places in the message view would find it handle to be
// able to compare messages to each other and opaque message ids as a
// data model make this difficult.
MessageModel.prototype.compareMessages = function(a, b) {
  return a.receiveTime - b.receiveTime;
};

function MessageTail(model, start, inclusive, cb) {
  this.model_ = model;
  // The last thing we sent.
  this.lastSent_ = start;
  // Whether the request is inclusive.
  this.inclusive_ = inclusive;
  // The number of messages sent total.
  this.messagesSentTotal_ = 0;
  // The number of messages sent since the last new-tail.
  this.messagesSentRecent_ = 0;
  // The number of messages we want ahead of lastSent_.
  this.messagesWanted_ = 0;
  // Callback. null on close.
  this.cb_ = cb;
  // The ID of the tail.
  this.tailId_ = null;
  // The value of the most recent extend-tail message.
  this.lastExtend_ = 0;

  // Hold onto these so we can unregister them.
  this.connectedCb_ = this.onConnect_.bind(this);
  this.disconnectCb_ = this.onDisconnect_.bind(this);
  this.messagesCb_ = this.onMessages_.bind(this);
  this.model_.api_.addEventListener("connect", this.connectedCb_);

  this.onConnect_();
}
MessageTail.prototype.onConnect_ = function() {
  // Unregister our old handlers.
  this.onDisconnect_();
  this.socket_ = this.model_.api_.socket();
  if (this.socket_) {
    this.socket_.addEventListener("messages", this.messagesCb_);
    this.socket_.sockJS().addEventListener("close", this.disconnectCb_);
    // Reset everything.
    this.createTail_();
    this.expandTo(0);
  }
};
MessageTail.prototype.onDisconnect_ = function() {
  if (this.socket_) {
    this.socket_.removeEventListener("messages", this.messagesCb_);
    this.socket_.sockJS().removeEventListener("close", this.disconnectCb_);
    this.socket_ = null;

    // We disconnected. Mark as not the end anymore.
    //
    // TODO(davidben): This makes scrollToEnd reset everything. Maybe
    // add a third "disconnected" state? Would also be good as far as
    // displaying a different message. Could also use API's
    // disconnected event and just leave this one be?
    if (this.cb_)
      this.cb_([], false);
  }
};
MessageTail.prototype.expandTo = function(count) {
  this.messagesWanted_ = Math.max(this.messagesWanted_,
                                  count - this.messagesSentTotal_);
  var newExtend = this.messagesWanted_ + this.messagesSentRecent_;
  if (this.socket_ && this.lastExtend_ < newExtend) {
    this.socket_.send({
      type: "extend-tail",
      id: this.tailId_,
      count:newExtend
    });
    this.lastExtend_ = newExtend;
  }
};
MessageTail.prototype.close = function() {
  if (this.socket_) {
    this.socket_.send({
      type: "close-tail",
      id: this.tailId_
    });
  }
  this.cb_ = null;
  this.model_.api_.removeEventListener("connect", this.connectedCb_);
  this.onDisconnect_();
{'fraction_non_alphanumeric': 0.11904761904761904, 'fraction_numerical': 0.0014697236919459142, 'mean_word_length': 3.4361147327249024, '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': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5414451', 'n_tokens_mistral': 2140, 'n_tokens_neox': 2093, 'n_words': 571}