| Index: src/js/messages.js
|
| diff --git a/src/js/messages.js b/src/js/messages.js
|
| index 1668a10eef9e81bbc3122dfd74172ebc49598aee..be33ff759b79dd0945f529636d881958f14924bc 100644
|
| --- a/src/js/messages.js
|
| +++ b/src/js/messages.js
|
| @@ -214,7 +214,7 @@
|
| var start_position = %MessageGetStartPosition(message);
|
| var location = script.locationFromPosition(start_position, true);
|
| if (location == null) return "";
|
| - return location.sourceText;
|
| + return location.sourceText();
|
| }
|
|
|
|
|
| @@ -225,27 +225,68 @@
|
| else the line number.
|
| */
|
| function ScriptLineFromPosition(position) {
|
| - var info = %ScriptPositionInfo(this, position, false);
|
| - return (info == null) ? -1 : info.line;
|
| + var lower = 0;
|
| + var upper = this.lineCount() - 1;
|
| + var line_ends = this.line_ends;
|
| +
|
| + // We'll never find invalid positions so bail right away.
|
| + if (position > line_ends[upper]) {
|
| + return -1;
|
| + }
|
| +
|
| + // This means we don't have to safe-guard indexing line_ends[i - 1].
|
| + if (position <= line_ends[0]) {
|
| + return 0;
|
| + }
|
| +
|
| + // Binary search to find line # from position range.
|
| + while (upper >= 1) {
|
| + var i = (lower + upper) >> 1;
|
| +
|
| + if (position > line_ends[i]) {
|
| + lower = i + 1;
|
| + } else if (position <= line_ends[i - 1]) {
|
| + upper = i - 1;
|
| + } else {
|
| + return i;
|
| + }
|
| + }
|
| +
|
| + return -1;
|
| }
|
|
|
|
|
| /**
|
| * Get information on a specific source position.
|
| - * Returns an object with the following following properties:
|
| - * script : script object for the source
|
| - * line : source line number
|
| - * column : source column within the line
|
| - * position : position within the source
|
| - * sourceText : a string containing the current line
|
| * @param {number} position The source position
|
| * @param {boolean} include_resource_offset Set to true to have the resource
|
| * offset added to the location
|
| - * @return If line is negative or not in the source null is returned.
|
| + * @return {SourceLocation}
|
| + * If line is negative or not in the source null is returned.
|
| */
|
| function ScriptLocationFromPosition(position,
|
| include_resource_offset) {
|
| - return %ScriptPositionInfo(this, position, !!include_resource_offset);
|
| + var line = this.lineFromPosition(position);
|
| + if (line == -1) return null;
|
| +
|
| + // Determine start, end and column.
|
| + var line_ends = this.line_ends;
|
| + var start = line == 0 ? 0 : line_ends[line - 1] + 1;
|
| + var end = line_ends[line];
|
| + if (end > 0 && %_StringCharAt(this.source, end - 1) === '\r') {
|
| + end--;
|
| + }
|
| + var column = position - start;
|
| +
|
| + // Adjust according to the offset within the resource.
|
| + if (include_resource_offset) {
|
| + line += this.line_offset;
|
| + if (line == this.line_offset) {
|
| + column += this.column_offset;
|
| + }
|
| + }
|
| +
|
| + return new SourceLocation(this, position, line, column, start, end);
|
| }
|
|
|
|
|
| @@ -261,7 +302,8 @@
|
| * @param {number} opt_offset_position The offset from the begining of the
|
| * source from where the line and column calculation starts.
|
| * Default value is 0
|
| - * @return If line is negative or not in the source null is returned.
|
| + * @return {SourceLocation}
|
| + * If line is negative or not in the source null is returned.
|
| */
|
| function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
|
| // Default is the first line in the script. Lines in the script is relative
|
| @@ -291,7 +333,7 @@
|
| }
|
|
|
| return this.locationFromPosition(
|
| - %ScriptLineStartPosition(this, offset_line + line) + column);
|
| + this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
|
| }
|
| }
|
|
|
| @@ -325,14 +367,15 @@
|
| return null;
|
| }
|
|
|
| - var from_position = %ScriptLineStartPosition(this, from_line);
|
| - var to_position = %ScriptLineStartPosition(this, to_line);
|
| + var line_ends = this.line_ends;
|
| + var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
|
| + var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
|
|
|
| // Return a source slice with line numbers re-adjusted to the resource.
|
| return new SourceSlice(this,
|
| from_line + this.line_offset,
|
| to_line + this.line_offset,
|
| - from_position, to_position);
|
| + from_position, to_position);
|
| }
|
|
|
|
|
| @@ -350,8 +393,9 @@
|
| }
|
|
|
| // Return the source line.
|
| - var start = %ScriptLineStartPosition(this, line);
|
| - var end = %ScriptLineEndPosition(this, line);
|
| + var line_ends = this.line_ends;
|
| + var start = line == 0 ? 0 : line_ends[line - 1] + 1;
|
| + var end = line_ends[line];
|
| return %_Call(StringSubstring, this.source, start, end);
|
| }
|
|
|
| @@ -363,7 +407,17 @@
|
| */
|
| function ScriptLineCount() {
|
| // Return number of source lines.
|
| - return %ScriptLineCount(this);
|
| + return this.line_ends.length;
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Returns the position of the nth line end.
|
| + * @return {number}
|
| + * Zero-based position of the nth line end in the script.
|
| + */
|
| +function ScriptLineEnd(n) {
|
| + return this.line_ends[n];
|
| }
|
|
|
|
|
| @@ -388,6 +442,7 @@
|
| "name",
|
| "source_url",
|
| "source_mapping_url",
|
| + "line_ends",
|
| "line_offset",
|
| "column_offset"
|
| ], [
|
| @@ -398,7 +453,55 @@
|
| "sourceLine", ScriptSourceLine,
|
| "lineCount", ScriptLineCount,
|
| "nameOrSourceURL", ScriptNameOrSourceURL,
|
| + "lineEnd", ScriptLineEnd
|
| ]
|
| +);
|
| +
|
| +
|
| +/**
|
| + * Class for source location. A source location is a position within some
|
| + * source with the following properties:
|
| + * script : script object for the source
|
| + * line : source line number
|
| + * column : source column within the line
|
| + * position : position within the source
|
| + * start : position of start of source context (inclusive)
|
| + * end : position of end of source context (not inclusive)
|
| + * Source text for the source context is the character interval
|
| + * [start, end[. In most cases end will point to a newline character.
|
| + * It might point just past the final position of the source if the last
|
| + * source line does not end with a newline character.
|
| + * @param {Script} script The Script object for which this is a location
|
| + * @param {number} position Source position for the location
|
| + * @param {number} line The line number for the location
|
| + * @param {number} column The column within the line for the location
|
| + * @param {number} start Source position for start of source context
|
| + * @param {number} end Source position for end of source context
|
| + * @constructor
|
| + */
|
| +function SourceLocation(script, position, line, column, start, end) {
|
| + this.script = script;
|
| + this.position = position;
|
| + this.line = line;
|
| + this.column = column;
|
| + this.start = start;
|
| + this.end = end;
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Get the source text for a SourceLocation
|
| + * @return {String}
|
| + * Source text for this location.
|
| + */
|
| +function SourceLocationSourceText() {
|
| + return %_Call(StringSubstring, this.script.source, this.start, this.end);
|
| +}
|
| +
|
| +
|
| +utils.SetUpLockedPrototype(SourceLocation,
|
| + ["script", "position", "line", "column", "start", "end"],
|
| + ["sourceText", SourceLocationSourceText]
|
| );
|
|
|
|
|
|
|