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