OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ------------------------------------------------------------------- | 5 // ------------------------------------------------------------------- |
6 | 6 |
7 var $errorToString; | 7 var $errorToString; |
8 var $getStackTraceLine; | 8 var $getStackTraceLine; |
9 var $messageGetPositionInLine; | 9 var $messageGetPositionInLine; |
10 var $messageGetLineNumber; | 10 var $messageGetLineNumber; |
(...skipping 22 matching lines...) Expand all Loading... |
33 %CheckIsBootstrapping(); | 33 %CheckIsBootstrapping(); |
34 | 34 |
35 // ------------------------------------------------------------------- | 35 // ------------------------------------------------------------------- |
36 // Imports | 36 // Imports |
37 | 37 |
38 var GlobalObject = global.Object; | 38 var GlobalObject = global.Object; |
39 var InternalArray = utils.InternalArray; | 39 var InternalArray = utils.InternalArray; |
40 var ObjectDefineProperty = utils.ObjectDefineProperty; | 40 var ObjectDefineProperty = utils.ObjectDefineProperty; |
41 | 41 |
42 var ArrayJoin; | 42 var ArrayJoin; |
| 43 var MathFloor; |
43 var ObjectToString; | 44 var ObjectToString; |
44 var StringCharAt; | 45 var StringCharAt; |
45 var StringIndexOf; | 46 var StringIndexOf; |
46 var StringSubstring; | 47 var StringSubstring; |
47 | 48 |
48 utils.Import(function(from) { | 49 utils.Import(function(from) { |
49 ArrayJoin = from.ArrayJoin; | 50 ArrayJoin = from.ArrayJoin; |
| 51 MathFloor = from.MathFloor; |
50 ObjectToString = from.ObjectToString; | 52 ObjectToString = from.ObjectToString; |
51 StringCharAt = from.StringCharAt; | 53 StringCharAt = from.StringCharAt; |
52 StringIndexOf = from.StringIndexOf; | 54 StringIndexOf = from.StringIndexOf; |
53 StringSubstring = from.StringSubstring; | 55 StringSubstring = from.StringSubstring; |
54 }); | 56 }); |
55 | 57 |
56 // ------------------------------------------------------------------- | 58 // ------------------------------------------------------------------- |
57 | 59 |
58 var GlobalError; | 60 var GlobalError; |
59 var GlobalTypeError; | 61 var GlobalTypeError; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 // Returns the source code line containing the given source | 198 // Returns the source code line containing the given source |
197 // position, or the empty string if the position is invalid. | 199 // position, or the empty string if the position is invalid. |
198 function GetSourceLine(message) { | 200 function GetSourceLine(message) { |
199 var script = %MessageGetScript(message); | 201 var script = %MessageGetScript(message); |
200 var start_position = %MessageGetStartPosition(message); | 202 var start_position = %MessageGetStartPosition(message); |
201 var location = script.locationFromPosition(start_position, true); | 203 var location = script.locationFromPosition(start_position, true); |
202 if (location == null) return ""; | 204 if (location == null) return ""; |
203 return location.sourceText(); | 205 return location.sourceText(); |
204 } | 206 } |
205 | 207 |
| 208 |
| 209 function Newlines(source, from, to, reduction) { |
| 210 var newLines = new InternalArray(); |
| 211 if (!IS_STRING(source)) return newLines; |
| 212 |
| 213 var length = source.length; |
| 214 for (; from < to && from < length && newLines.length < reduction - 1 |
| 215 ; ++from) { |
| 216 var c = %_StringCharCodeAt(source, from); |
| 217 if (c == ASCII_CR) { |
| 218 if (from < length - 1) { |
| 219 var c2 = %_StringCharCodeAt(source, from + 1); |
| 220 if (c2 == ASCII_NL) { |
| 221 from++; // CR-LF counts as one newline. |
| 222 } |
| 223 } |
| 224 newLines.push(from); |
| 225 } else if (c == ASCII_NL) { |
| 226 newLines.push(from); |
| 227 } |
| 228 } |
| 229 // End-of-file virtual end-of-line. |
| 230 if (to >= length) { |
| 231 var last = length != 0 ? %_StringCharCodeAt(source, length - 1) : 0; |
| 232 if (last != ASCII_NL && last != ASCII_CR) newLines.push(source.length - 1); |
| 233 } |
| 234 return newLines; |
| 235 } |
| 236 |
| 237 |
| 238 function ScriptLineEnd(line) { |
| 239 if (line < 0) return -1; |
| 240 var source = this.source; |
| 241 if (!IS_STRING(source)) return -1; |
| 242 var line_ends = this.line_ends; |
| 243 var reduction = line_ends[REDUCTION_INDEX]; |
| 244 var index = MathFloor(line / reduction) + FIRST_LINE_END_INDEX; |
| 245 if (index >= line_ends.length) return -1; |
| 246 var position = line_ends[index]; |
| 247 if (line % reduction == 0) return position; |
| 248 var lines = Newlines(source, position + 1, source.length, reduction); |
| 249 return lines[line % reduction - 1]; |
| 250 } |
| 251 |
| 252 |
206 /** | 253 /** |
207 * Find a line number given a specific source position. | 254 * Find a line number given a specific source position. |
208 * @param {number} position The source position. | 255 * @param {number} position The source position. |
209 * @return {number} 0 if input too small, -1 if input too large, | 256 * @return {number} -1 if position too large, else the 0-based line number. |
210 else the line number. | |
211 */ | 257 */ |
212 function ScriptLineFromPosition(position) { | 258 function ScriptLineFromPosition(position) { |
213 var lower = 0; | 259 var source = this.source; |
214 var upper = this.lineCount() - 1; | 260 if (!IS_STRING(source)) return -1; |
| 261 |
215 var line_ends = this.line_ends; | 262 var line_ends = this.line_ends; |
| 263 var lower = FIRST_LINE_END_INDEX; |
| 264 var upper = line_ends.length - 1; |
216 | 265 |
217 // We'll never find invalid positions so bail right away. | 266 var reduction = line_ends[REDUCTION_INDEX]; |
| 267 // This '>' would normally be a '>=', but due to {}-less 'with' statements in |
| 268 // top-level code we sometimes encounter code positions that are one character |
| 269 // after the end of the source. See comment in Rewriter::Rewrite. |
| 270 if (position > source.length) return -1; |
| 271 |
| 272 var index = 0; |
| 273 |
| 274 // Binary search to find line # from position range. |
218 if (position > line_ends[upper]) { | 275 if (position > line_ends[upper]) { |
219 return -1; | 276 index = upper; |
| 277 } else { |
| 278 // Invariant: position > line_ends[lower] |
| 279 // Invariant: position <= line_ends[upper] |
| 280 while (lower + 1 < upper) { |
| 281 // Since they differ by at least 2, i must be different from both |
| 282 // upper or lower. |
| 283 var i = (lower + upper) >> 1; |
| 284 if (position > line_ends[i]) { |
| 285 lower = i; |
| 286 } else { |
| 287 upper = i; |
| 288 } |
| 289 } |
| 290 index = lower; |
220 } | 291 } |
221 | 292 |
222 // This means we don't have to safe-guard indexing line_ends[i - 1]. | 293 var line = (index - FIRST_LINE_END_INDEX) * reduction; |
223 if (position <= line_ends[0]) { | 294 return line + |
224 return 0; | 295 Newlines(source, line_ends[index] + 1, position, reduction).length; |
225 } | |
226 | |
227 // Binary search to find line # from position range. | |
228 while (upper >= 1) { | |
229 var i = (lower + upper) >> 1; | |
230 | |
231 if (position > line_ends[i]) { | |
232 lower = i + 1; | |
233 } else if (position <= line_ends[i - 1]) { | |
234 upper = i - 1; | |
235 } else { | |
236 return i; | |
237 } | |
238 } | |
239 | |
240 return -1; | |
241 } | 296 } |
242 | 297 |
243 /** | 298 /** |
244 * Get information on a specific source position. | 299 * Get information on a specific source position. |
245 * @param {number} position The source position | 300 * @param {number} position The source position |
246 * @param {boolean} include_resource_offset Set to true to have the resource | 301 * @param {boolean} include_resource_offset Set to true to have the resource |
247 * offset added to the location | 302 * offset added to the location |
248 * @return {SourceLocation} | 303 * @return {SourceLocation} |
249 * If line is negative or not in the source null is returned. | 304 * If line is negative or not in the source null is returned. |
250 */ | 305 */ |
251 function ScriptLocationFromPosition(position, | 306 function ScriptLocationFromPosition(position, |
252 include_resource_offset) { | 307 include_resource_offset) { |
| 308 // Get zero-based line number. |
253 var line = this.lineFromPosition(position); | 309 var line = this.lineFromPosition(position); |
254 if (line == -1) return null; | 310 if (line == -1) return null; |
255 | 311 |
256 // Determine start, end and column. | 312 // Determine start, end and column. |
257 var line_ends = this.line_ends; | 313 var start = this.lineEnd(line) + 1; |
258 var start = line == 0 ? 0 : line_ends[line - 1] + 1; | 314 // End will be used for substr, so make it non-inclusive. |
259 var end = line_ends[line]; | 315 var end = this.lineEnd(line + 1) + 1; |
260 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') { | 316 if (end > this.source.length) end = this.source.length; |
| 317 // But trim the newline if there is one (there might not be at EOF). |
| 318 while (end > start) { |
| 319 var trim_char = %_CallFunction(this.source, end - 1, StringCharAt); |
| 320 if (trim_char != '\n' && trim_char != '\r') break; |
261 end--; | 321 end--; |
262 } | 322 } |
263 var column = position - start; | 323 var column = position - start; |
264 | 324 |
265 // Adjust according to the offset within the resource. | 325 // Adjust according to the offset within the resource. |
266 if (include_resource_offset) { | 326 if (include_resource_offset) { |
267 line += this.line_offset; | 327 line += this.line_offset; |
268 if (line == this.line_offset) { | 328 if (line == this.line_offset) { |
269 column += this.column_offset; | 329 column += this.column_offset; |
270 } | 330 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 return this.locationFromPosition(offset_position + column, false); | 370 return this.locationFromPosition(offset_position + column, false); |
311 } else { | 371 } else { |
312 // Find the line where the offset position is located. | 372 // Find the line where the offset position is located. |
313 var offset_line = this.lineFromPosition(offset_position); | 373 var offset_line = this.lineFromPosition(offset_position); |
314 | 374 |
315 if (offset_line == -1 || offset_line + line >= this.lineCount()) { | 375 if (offset_line == -1 || offset_line + line >= this.lineCount()) { |
316 return null; | 376 return null; |
317 } | 377 } |
318 | 378 |
319 return this.locationFromPosition( | 379 return this.locationFromPosition( |
320 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here. | 380 this.lineEnd(offset_line + line) + 1 + column); // line > 0 here. |
321 } | 381 } |
322 } | 382 } |
323 | 383 |
324 | 384 |
325 /** | 385 /** |
326 * Get a slice of source code from the script. The boundaries for the slice is | 386 * Get a slice of source code from the script. The boundaries for the slice is |
327 * specified in lines. | 387 * specified in lines. |
328 * @param {number} opt_from_line The first line (zero bound) in the slice. | 388 * @param {number} opt_from_line The first line (zero bound) in the slice. |
329 * Default is 0 | 389 * Default is 0 |
330 * @param {number} opt_to_column The last line (zero bound) in the slice (non | 390 * @param {number} opt_to_column The last line (zero bound) in the slice (non |
(...skipping 13 matching lines...) Expand all Loading... |
344 if (from_line < 0) from_line = 0; | 404 if (from_line < 0) from_line = 0; |
345 if (to_line > this.lineCount()) to_line = this.lineCount(); | 405 if (to_line > this.lineCount()) to_line = this.lineCount(); |
346 | 406 |
347 // Check parameters. | 407 // Check parameters. |
348 if (from_line >= this.lineCount() || | 408 if (from_line >= this.lineCount() || |
349 to_line < 0 || | 409 to_line < 0 || |
350 from_line > to_line) { | 410 from_line > to_line) { |
351 return null; | 411 return null; |
352 } | 412 } |
353 | 413 |
354 var line_ends = this.line_ends; | 414 var from_position = this.lineEnd(from_line) + 1; |
355 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1; | 415 var to_position = this.lineEnd(to_line) + 1; |
356 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1; | |
357 | 416 |
358 // Return a source slice with line numbers re-adjusted to the resource. | 417 // Return a source slice with line numbers re-adjusted to the resource. |
359 return new SourceSlice(this, | 418 return new SourceSlice(this, |
360 from_line + this.line_offset, | 419 from_line + this.line_offset, |
361 to_line + this.line_offset, | 420 to_line + this.line_offset, |
362 from_position, to_position); | 421 from_position, to_position); |
363 } | 422 } |
364 | 423 |
365 | 424 |
366 function ScriptSourceLine(opt_line) { | 425 function ScriptSourceLine(opt_line) { |
367 // Default is the first line in the script. Lines in the script are relative | 426 // Default is the first line in the script. Lines in the script are relative |
368 // to the offset within the resource. | 427 // to the offset within the resource. |
369 var line = 0; | 428 var line = 0; |
370 if (!IS_UNDEFINED(opt_line)) { | 429 if (!IS_UNDEFINED(opt_line)) { |
371 line = opt_line - this.line_offset; | 430 line = opt_line - this.line_offset; |
372 } | 431 } |
373 | 432 |
374 // Check parameter. | 433 // Check parameter. |
375 if (line < 0 || this.lineCount() <= line) { | 434 if (line < 0 || this.lineCount() <= line) { |
376 return null; | 435 return null; |
377 } | 436 } |
378 | 437 |
379 // Return the source line. | 438 // Return the source line. |
380 var line_ends = this.line_ends; | 439 var start = this.lineEnd(line) + 1; |
381 var start = line == 0 ? 0 : line_ends[line - 1] + 1; | 440 var end = this.lineEnd(line + 1); |
382 var end = line_ends[line]; | |
383 return %_CallFunction(this.source, start, end, StringSubstring); | 441 return %_CallFunction(this.source, start, end, StringSubstring); |
384 } | 442 } |
385 | 443 |
386 | 444 |
387 /** | 445 /** |
388 * Returns the number of source lines. | 446 * Returns the number of source lines. |
389 * @return {number} | 447 * @return {number} |
390 * Number of source lines. | 448 * Number of source lines. |
391 */ | 449 */ |
392 function ScriptLineCount() { | 450 function ScriptLineCount() { |
393 // Return number of source lines. | 451 // Return number of source lines. |
394 return this.line_ends.length; | 452 return this.line_ends[NUMBER_OF_LINES_INDEX]; |
395 } | 453 } |
396 | 454 |
397 | 455 |
398 /** | 456 /** |
399 * If sourceURL comment is available returns sourceURL comment contents. | 457 * If sourceURL comment is available returns sourceURL comment contents. |
400 * Otherwise, script name is returned. See | 458 * Otherwise, script name is returned. See |
401 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt | 459 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt |
402 * and Source Map Revision 3 proposal for details on using //# sourceURL and | 460 * and Source Map Revision 3 proposal for details on using //# sourceURL and |
403 * deprecated //@ sourceURL comment to identify scripts that don't have name. | 461 * deprecated //@ sourceURL comment to identify scripts that don't have name. |
404 * | 462 * |
(...skipping 14 matching lines...) Expand all Loading... |
419 "line_ends", | 477 "line_ends", |
420 "line_offset", | 478 "line_offset", |
421 "column_offset" | 479 "column_offset" |
422 ], [ | 480 ], [ |
423 "lineFromPosition", ScriptLineFromPosition, | 481 "lineFromPosition", ScriptLineFromPosition, |
424 "locationFromPosition", ScriptLocationFromPosition, | 482 "locationFromPosition", ScriptLocationFromPosition, |
425 "locationFromLine", ScriptLocationFromLine, | 483 "locationFromLine", ScriptLocationFromLine, |
426 "sourceSlice", ScriptSourceSlice, | 484 "sourceSlice", ScriptSourceSlice, |
427 "sourceLine", ScriptSourceLine, | 485 "sourceLine", ScriptSourceLine, |
428 "lineCount", ScriptLineCount, | 486 "lineCount", ScriptLineCount, |
429 "nameOrSourceURL", ScriptNameOrSourceURL | 487 "nameOrSourceURL", ScriptNameOrSourceURL, |
| 488 "lineEnd", ScriptLineEnd |
430 ] | 489 ] |
431 ); | 490 ); |
432 | 491 |
433 | 492 |
434 /** | 493 /** |
435 * Class for source location. A source location is a position within some | 494 * Class for source location. A source location is a position within some |
436 * source with the following properties: | 495 * source with the following properties: |
437 * script : script object for the source | 496 * script : script object for the source |
438 * line : source line number | 497 * line : source line number |
439 * column : source column within the line | 498 * column : source column within the line |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 // Define accessors first, as this may fail and throw. | 1141 // Define accessors first, as this may fail and throw. |
1083 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter, | 1142 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter, |
1084 set: StackTraceSetter, | 1143 set: StackTraceSetter, |
1085 configurable: true }); | 1144 configurable: true }); |
1086 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace); | 1145 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace); |
1087 }; | 1146 }; |
1088 | 1147 |
1089 GlobalError.captureStackTrace = captureStackTrace; | 1148 GlobalError.captureStackTrace = captureStackTrace; |
1090 | 1149 |
1091 }); | 1150 }); |
OLD | NEW |