| Index: src/messages.js
 | 
| ===================================================================
 | 
| --- src/messages.js	(revision 2123)
 | 
| +++ src/messages.js	(working copy)
 | 
| @@ -230,7 +230,41 @@
 | 
|    return MakeGenericError($Error, type, args);
 | 
|  }
 | 
|  
 | 
| +/**
 | 
| + * Find a line number given a specific source position.
 | 
| + * @param {number} position The source position.
 | 
| + * @return {number} 0 if input too small, -1 if input too large,
 | 
| +       else the line number.
 | 
| + */
 | 
| +Script.prototype.lineFromPosition = function(position) {
 | 
| +  var lower = 0;
 | 
| +  var upper = this.lineCount() - 1;
 | 
|  
 | 
| +  // We'll never find invalid positions so bail right away.
 | 
| +  if (position > this.line_ends[upper]) {
 | 
| +    return -1;
 | 
| +  }
 | 
| +
 | 
| +  // This means we don't have to safe-guard indexing line_ends[i - 1].
 | 
| +  if (position <= this.line_ends[0]) {
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  // Binary search to find line # from position range.
 | 
| +  while (upper >= 1) {
 | 
| +    var i = (lower + upper) >> 1;
 | 
| +
 | 
| +    if (position > this.line_ends[i]) {
 | 
| +      lower = i + 1;
 | 
| +    } else if (position <= this.line_ends[i - 1]) {
 | 
| +      upper = i - 1;
 | 
| +    } else {
 | 
| +      return i;
 | 
| +    }
 | 
| +  }
 | 
| +  return -1;
 | 
| +}
 | 
| +
 | 
|  /**
 | 
|   * Get information on a specific source position.
 | 
|   * @param {number} position The source position
 | 
| @@ -241,19 +275,7 @@
 | 
|   */
 | 
|  Script.prototype.locationFromPosition = function (position,
 | 
|                                                    include_resource_offset) {
 | 
| -  var lineCount = this.lineCount();
 | 
| -  var line = -1;
 | 
| -  if (position <= this.line_ends[0]) {
 | 
| -    line = 0;
 | 
| -  } else {
 | 
| -    for (var i = 1; i < lineCount; i++) {
 | 
| -      if (this.line_ends[i - 1] < position && position <= this.line_ends[i]) {
 | 
| -        line = i;
 | 
| -        break;
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| +  var line = this.lineFromPosition(position);
 | 
|    if (line == -1) return null;
 | 
|  
 | 
|    // Determine start, end and column.
 | 
| @@ -308,16 +330,13 @@
 | 
|    if (line == 0) {
 | 
|      return this.locationFromPosition(offset_position + column, false);
 | 
|    } else {
 | 
| -    // Find the line where the offset position is located
 | 
| -    var lineCount = this.lineCount();
 | 
| -    var offset_line;
 | 
| -    for (var i = 0; i < lineCount; i++) {
 | 
| -      if (offset_position <= this.line_ends[i]) {
 | 
| -        offset_line = i;
 | 
| -        break;
 | 
| -      }
 | 
| +    // Find the line where the offset position is located.
 | 
| +    var offset_line = this.lineFromPosition(offset_position);
 | 
| +
 | 
| +    if (offset_line == -1 || offset_line + line >= this.lineCount()) {
 | 
| +      return null;
 | 
|      }
 | 
| -    if (offset_line + line >= lineCount) return null;
 | 
| +
 | 
|      return this.locationFromPosition(this.line_ends[offset_line + line - 1] + 1 + column);  // line > 0 here.
 | 
|    }
 | 
|  }
 | 
| 
 |