 
     {startScreenRow, endScreenRow, startBufferRow, endBufferRow}
 
-  buildSpatialScreenLines: (startBufferRow, endBufferRow) ->
+  computeSpatialScreenLinesThroughBufferRow: (bufferRow) ->
+    @computeSpatialScreenLines(bufferRow + 1, Infinity)
+
+  computeSpatialScreenLinesThroughScreenRow: (screenRow) ->
+    @computeSpatialScreenLines(Infinity, screenRow + 1)
+
+  computeSpatialScreenLines: (endBufferRow, endScreenRow) ->
+    return if @processingBufferChange
+    if @indexedBufferRowCount < Math.min(endBufferRow, @buffer.getLineCount())
+      lastScreenRow = @displayIndex.getScreenLineCount()
+      if lastScreenRow < endScreenRow
+        {spatialScreenLines, endBufferRow} = @buildSpatialScreenLines(
+          @indexedBufferRowCount,
+          endBufferRow,
+          endScreenRow - lastScreenRow
+        )
+        @spliceDisplayIndex(lastScreenRow, Infinity, spatialScreenLines)
+        @indexedBufferRowCount = endBufferRow
+
+  buildSpatialScreenLines: (startBufferRow, endBufferRow, screenLineCount = Infinity) ->
     {startBufferRow, endBufferRow, folds} = @computeFoldsInBufferRowRange(startBufferRow, endBufferRow)
 
-    screenLines = []
+    spatialScreenLines = []
     bufferRow = startBufferRow
     bufferColumn = 0
     screenColumn = 0
     screenLineWidth = 0
 
-    while bufferRow < endBufferRow
+    while bufferRow < endBufferRow and spatialScreenLines.length < screenLineCount
       tokens = []
       tokensScreenExtent = 0
       screenLineBufferStart = Point(bufferRow, 0)
       bufferLine = @buffer.lineForRow(bufferRow)
+      break unless bufferLine?
       bufferLineLength = bufferLine.length
       previousPositionWasFold = false
       trailingWhitespaceStartBufferColumn = @findTrailingWhitespaceStartBufferColumn(bufferLine)

    {oldRange, newRange}

  lineStartBoundaryForBufferRow: (bufferRow) ->
    @spatialLineIterator.seekToBufferPosition(Point(bufferRow, 0))
    while @spatialLineIterator.isSoftWrappedAtStart()
      @spatialLineIterator.moveToPredecessor()

    combinedRange = Range(combinedRangeStart, combinedRangeEnd)
    {startScreenRow, endScreenRow, startBufferRow, endBufferRow} = @expandBufferRangeToLineBoundaries(combinedRange)
    oldRowExtent = endScreenRow - startScreenRow
    {spatialScreenLines} = @buildSpatialScreenLines(startBufferRow, endBufferRow)
    newRowExtent = spatialScreenLines.length
    @spliceDisplayIndex(startScreenRow, oldRowExtent, spatialScreenLines)
    @emitDidChangeSyncEvent Object.freeze([{
      start: Point(startScreenRow, 0),
      oldExtent: Point(oldRowExtent, 0),
