function TextRange(document, startLine, endLine) {
        this.startLine = startLine;
        this.endLine = endLine;

        this.document = document;
        document.addRef();
        // store this-bound versions of listeners so we can remove them later
        this._handleDocumentChange = this._handleDocumentChange.bind(this);
        this._handleDocumentDeleted = this._handleDocumentDeleted.bind(this);
        document.on("change", this._handleDocumentChange);
        document.on("deleted", this._handleDocumentDeleted);
    }
Stores a range of lines that is automatically maintained as the Document changes. The range
MAY drop out of sync with the Document in certain edge cases; startLine & endLine will become
null when that happens.

Important: you must dispose() a TextRange when you're done with it. Because TextRange addRef()s
the Document (in order to listen to it), you will leak Documents otherwise.

TextRange dispatches these events:
 - change -- When the range boundary line numbers change (due to a Document change)
 - contentChange -- When the actual content of the range changes. This might or might not
   be accompanied by a change in the boundary line numbers.
 - lostSync -- When the backing Document changes in such a way that the range can no longer
   accurately be maintained. Generally, occurs whenever an edit spans a range boundary.
   After this, startLine & endLine will be unusable (set to null).
   Also occurs when the document is deleted, though startLine & endLine won't be modified
These events only ever occur in response to Document changes, so if you are already listening
to the Document, you could ignore the TextRange events and just read its updated value in your
own Document change handler.

@constructor

@param {!Document} document
@param {number} startLine First line in range (0-based, inclusive)
@param {number} endLine   Last line in range (0-based, inclusive)