Author: [email protected]
Date: Tue Jun 9 00:03:21 2009
New Revision: 2125
Modified:
branches/bleeding_edge/src/messages.js
branches/bleeding_edge/test/mjsunit/debug-sourceinfo.js
Log:
Change locationFromPosition() and locationFromLine() to use a binary search
to locate line numbers from position numbers. Modify test
debug-sourceinfo.js to include more tests, including error conditions.
Patch by Matt Hanselman, see http://codereview.chromium.org/118371.
BUG=213
TEST=test/mjsunit/debug-sourceinfo.js
Review URL: http://codereview.chromium.org/118425
Modified: branches/bleeding_edge/src/messages.js
==============================================================================
--- branches/bleeding_edge/src/messages.js (original)
+++ branches/bleeding_edge/src/messages.js Tue Jun 9 00:03:21 2009
@@ -230,6 +230,40 @@
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.
@@ -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.
}
}
Modified: branches/bleeding_edge/test/mjsunit/debug-sourceinfo.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/debug-sourceinfo.js (original)
+++ branches/bleeding_edge/test/mjsunit/debug-sourceinfo.js Tue Jun 9
00:03:21 2009
@@ -38,6 +38,23 @@
return 1;
}
};
+function d(x) {
+ x = 1 ;
+ x = 2 ;
+ x = 3 ;
+ x = 4 ;
+ x = 5 ;
+ x = 6 ;
+ x = 7 ;
+ x = 8 ;
+ x = 9 ;
+ x = 10;
+ x = 11;
+ x = 12;
+ x = 13;
+ x = 14;
+ x = 15;
+}
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
@@ -45,22 +62,42 @@
// This is the number of comment lines above the first test function.
var comment_lines = 29;
+// This is the last position in the entire file (note: this equals
+// file size of <debug-sourceinfo.js> - 1, since starting at 0).
+var last_position = 14072;
+// This is the last line of entire file (note: starting at 0).
+var last_line = 345;
+// This is the last column of last line (note: starting at 0 and +2, due
+// to trailing <CR><LF>).
+var last_column = 48;
+
// This magic number is the length or the first line comment (actually
number
// of characters before 'function a(...'.
var comment_line_length = 1726;
var start_a = 10 + comment_line_length;
var start_b = 37 + comment_line_length;
var start_c = 71 + comment_line_length;
+var start_d = 163 + comment_line_length;
+
+// The position of the first line of d(), i.e. "x = 1 ;".
+var start_code_d = start_d + 7;
+// The line # of the first line of d() (note: starting at 0).
+var start_line_d = 41;
+var line_length_d = 11;
+var num_lines_d = 15;
assertEquals(start_a, Debug.sourcePosition(a));
assertEquals(start_b, Debug.sourcePosition(b));
assertEquals(start_c, Debug.sourcePosition(c));
+assertEquals(start_d, Debug.sourcePosition(d));
var script = Debug.findScript(a);
assertTrue(script.data === Debug.findScript(b).data);
assertTrue(script.data === Debug.findScript(c).data);
+assertTrue(script.data === Debug.findScript(d).data);
assertTrue(script.source === Debug.findScript(b).source);
assertTrue(script.source === Debug.findScript(c).source);
+assertTrue(script.source === Debug.findScript(d).source);
// Test that when running through source positions the position, line and
// column progresses as expected.
@@ -89,6 +126,19 @@
column = location.column;
}
+// Every line of d() is the same length. Verify we can loop through all
+// positions and find the right line # for each.
+var p = start_code_d;
+for (line = 0; line < num_lines_d; line++) {
+ for (column = 0; column < line_length_d; column++) {
+ var location = script.locationFromPosition(p);
+ assertEquals(p, location.position);
+ assertEquals(start_line_d + line, location.line);
+ assertEquals(column, location.column);
+ p++;
+ }
+}
+
// Test first position.
assertEquals(0, script.locationFromPosition(0).position);
assertEquals(0, script.locationFromPosition(0).line);
@@ -99,21 +149,26 @@
assertEquals(0, script.locationFromPosition(1).line);
assertEquals(1, script.locationFromPosition(1).column);
-// Test first position in finction a.
+// Test first position in function a().
assertEquals(start_a, script.locationFromPosition(start_a).position);
assertEquals(0, script.locationFromPosition(start_a).line - comment_lines);
assertEquals(10, script.locationFromPosition(start_a).column);
-// Test first position in finction b.
+// Test first position in function b().
assertEquals(start_b, script.locationFromPosition(start_b).position);
assertEquals(1, script.locationFromPosition(start_b).line - comment_lines);
assertEquals(13, script.locationFromPosition(start_b).column);
-// Test first position in finction b.
+// Test first position in function c().
assertEquals(start_c, script.locationFromPosition(start_c).position);
assertEquals(4, script.locationFromPosition(start_c).line - comment_lines);
assertEquals(12, script.locationFromPosition(start_c).column);
+// Test first position in function d().
+assertEquals(start_d, script.locationFromPosition(start_d).position);
+assertEquals(11, script.locationFromPosition(start_d).line -
comment_lines);
+assertEquals(10, script.locationFromPosition(start_d).column);
+
// Test first line.
assertEquals(0, script.locationFromLine().position);
assertEquals(0, script.locationFromLine().line);
@@ -122,17 +177,17 @@
assertEquals(0, script.locationFromLine(0).line);
assertEquals(0, script.locationFromLine(0).column);
-// Test first line column 1
+// Test first line column 1.
assertEquals(1, script.locationFromLine(0, 1).position);
assertEquals(0, script.locationFromLine(0, 1).line);
assertEquals(1, script.locationFromLine(0, 1).column);
-// Test first line offset 1
+// Test first line offset 1.
assertEquals(1, script.locationFromLine(0, 0, 1).position);
assertEquals(0, script.locationFromLine(0, 0, 1).line);
assertEquals(1, script.locationFromLine(0, 0, 1).column);
-// Test offset function a
+// Test offset function a().
assertEquals(start_a, script.locationFromLine(void 0, void 0,
start_a).position);
assertEquals(0, script.locationFromLine(void 0, void 0, start_a).line -
comment_lines);
assertEquals(10, script.locationFromLine(void 0, void 0, start_a).column);
@@ -143,27 +198,27 @@
assertEquals(0, script.locationFromLine(0, 0, start_a).line -
comment_lines);
assertEquals(10, script.locationFromLine(0, 0, start_a).column);
-// Test second line offset function a
+// Test second line offset function a().
assertEquals(start_a + 14, script.locationFromLine(1, 0,
start_a).position);
assertEquals(1, script.locationFromLine(1, 0, start_a).line -
comment_lines);
assertEquals(0, script.locationFromLine(1, 0, start_a).column);
-// Test second line column 2 offset function a
+// Test second line column 2 offset function a().
assertEquals(start_a + 14 + 2, script.locationFromLine(1, 2,
start_a).position);
assertEquals(1, script.locationFromLine(1, 2, start_a).line -
comment_lines);
assertEquals(2, script.locationFromLine(1, 2, start_a).column);
-// Test offset function b
+// Test offset function b().
assertEquals(start_b, script.locationFromLine(0, 0, start_b).position);
assertEquals(1, script.locationFromLine(0, 0, start_b).line -
comment_lines);
assertEquals(13, script.locationFromLine(0, 0, start_b).column);
-// Test second line offset function b
+// Test second line offset function b().
assertEquals(start_b + 6, script.locationFromLine(1, 0, start_b).position);
assertEquals(2, script.locationFromLine(1, 0, start_b).line -
comment_lines);
assertEquals(0, script.locationFromLine(1, 0, start_b).column);
-// Test second line column 11 offset function b
+// Test second line column 11 offset function b().
assertEquals(start_b + 6 + 11, script.locationFromLine(1, 11,
start_b).position);
assertEquals(2, script.locationFromLine(1, 11, start_b).line -
comment_lines);
assertEquals(11, script.locationFromLine(1, 11, start_b).column);
@@ -187,6 +242,21 @@
assertEquals(52 + start_c, Debug.findFunctionSourceLocation(c, 4,
0).position);
assertEquals(69 + start_c, Debug.findFunctionSourceLocation(c, 5,
0).position);
assertEquals(76 + start_c, Debug.findFunctionSourceLocation(c, 6,
0).position);
+assertEquals(0 + start_d, Debug.findFunctionSourceLocation(d, 0,
0).position);
+assertEquals(7 + start_d, Debug.findFunctionSourceLocation(d, 1,
0).position);
+for (i = 1; i <= num_lines_d; i++) {
+ assertEquals(7 + (i * line_length_d) + start_d,
Debug.findFunctionSourceLocation(d, (i + 1), 0).position);
+}
+assertEquals(175 + start_d, Debug.findFunctionSourceLocation(d, 17,
0).position);
+
+// Make sure invalid inputs work properly.
+assertEquals(0, script.locationFromPosition(-1).line);
+assertEquals(null, script.locationFromPosition(last_position + 1));
+
+// Test last position.
+assertEquals(last_position,
script.locationFromPosition(last_position).position);
+assertEquals(last_line, script.locationFromPosition(last_position).line);
+assertEquals(last_column,
script.locationFromPosition(last_position).column);
// Test source line and restriction. All the following tests start from
line 1
// column 2 in function b, which is the call to c.
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---