docs: function readyStateChangeHandler(readyState, abort){
      var newState;
      var newStateData;
      var error = false;
  
      if (typeof readyState != 'number')
      {
        // nothing to do if event for previous script fired
        if (!readyState || this.script !== readyState.target)
          return;
  
        error = readyState && readyState.type == 'error';
        readyState = error || !this.script.readyState || /loaded|complete/.test(this.script.readyState) ? STATE_DONE : STATE_LOADING;
      }
  
      if (readyState == this.prevReadyState_)
        return;
  
      this.prevReadyState_ = readyState;
  
      // dispatch self event
      this.emit_readyStateChanged(readyState);
  
      if (readyState == STATE_DONE)
      {
        this.clearTimeout();
  
        // remove event handlers
        this.script.onload = this.script.onerror = this.script.onreadystatechange = null;
  
        // remove the script
        if (this.script.parentNode)
          this.script.parentNode.removeChild(this.script);
  
        // dereference the script
        this.script = null;
  
        if (abort)
        {
          this.emit_abort();
          newState = this.stateOnAbort;
        }
        else
        {
          this.processResponse();
  
          // dispatch events
          if (this.isSuccessful() && !error)
          {
            newState = STATE.READY;
  
            this.emit_success(this.getResponseData());
          }
          else
          {
            newState = STATE.ERROR;
            newStateData = this.getResponseError();
  
            this.emit_failure(newStateData);
          }
        }
  
        // dispatch complete event
        this.emit_complete(this);
  
        // cleanup callback
        var callback = this.callback;
        if (abort)
        {
          // if request aborted delete callback in 5 mins or on callback invocation
          setTimeout(global[callback] = function(){
            releaseCallback(callback);
          }, 5 * 60 * 1000);
        }
        else
        {
          // otherwise release callback immediately
          releaseCallback(callback);
        }
      }
      else
        newState = STATE.PROCESSING;
  
      // set new state
      this.setState(newState, newStateData);
    }