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 (function(global, utils) { | 7 (function(global, utils) { |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 } | 207 } |
208 | 208 |
209 | 209 |
210 // Returns the source code line containing the given source | 210 // Returns the source code line containing the given source |
211 // position, or the empty string if the position is invalid. | 211 // position, or the empty string if the position is invalid. |
212 function GetSourceLine(message) { | 212 function GetSourceLine(message) { |
213 var script = %MessageGetScript(message); | 213 var script = %MessageGetScript(message); |
214 var start_position = %MessageGetStartPosition(message); | 214 var start_position = %MessageGetStartPosition(message); |
215 var location = script.locationFromPosition(start_position, true); | 215 var location = script.locationFromPosition(start_position, true); |
216 if (location == null) return ""; | 216 if (location == null) return ""; |
217 return location.sourceText; | 217 return location.sourceText(); |
218 } | 218 } |
219 | 219 |
220 | 220 |
221 /** | 221 /** |
222 * Find a line number given a specific source position. | 222 * Find a line number given a specific source position. |
223 * @param {number} position The source position. | 223 * @param {number} position The source position. |
224 * @return {number} 0 if input too small, -1 if input too large, | 224 * @return {number} 0 if input too small, -1 if input too large, |
225 else the line number. | 225 else the line number. |
226 */ | 226 */ |
227 function ScriptLineFromPosition(position) { | 227 function ScriptLineFromPosition(position) { |
228 var info = %ScriptPositionInfo(this, position, false); | 228 var lower = 0; |
229 return (info == null) ? -1 : info.line; | 229 var upper = this.lineCount() - 1; |
| 230 var line_ends = this.line_ends; |
| 231 |
| 232 // We'll never find invalid positions so bail right away. |
| 233 if (position > line_ends[upper]) { |
| 234 return -1; |
| 235 } |
| 236 |
| 237 // This means we don't have to safe-guard indexing line_ends[i - 1]. |
| 238 if (position <= line_ends[0]) { |
| 239 return 0; |
| 240 } |
| 241 |
| 242 // Binary search to find line # from position range. |
| 243 while (upper >= 1) { |
| 244 var i = (lower + upper) >> 1; |
| 245 |
| 246 if (position > line_ends[i]) { |
| 247 lower = i + 1; |
| 248 } else if (position <= line_ends[i - 1]) { |
| 249 upper = i - 1; |
| 250 } else { |
| 251 return i; |
| 252 } |
| 253 } |
| 254 |
| 255 return -1; |
230 } | 256 } |
231 | 257 |
232 | 258 |
233 /** | 259 /** |
234 * Get information on a specific source position. | 260 * Get information on a specific source position. |
235 * Returns an object with the following following properties: | |
236 * script : script object for the source | |
237 * line : source line number | |
238 * column : source column within the line | |
239 * position : position within the source | |
240 * sourceText : a string containing the current line | |
241 * @param {number} position The source position | 261 * @param {number} position The source position |
242 * @param {boolean} include_resource_offset Set to true to have the resource | 262 * @param {boolean} include_resource_offset Set to true to have the resource |
243 * offset added to the location | 263 * offset added to the location |
244 * @return If line is negative or not in the source null is returned. | 264 * @return {SourceLocation} |
| 265 * If line is negative or not in the source null is returned. |
245 */ | 266 */ |
246 function ScriptLocationFromPosition(position, | 267 function ScriptLocationFromPosition(position, |
247 include_resource_offset) { | 268 include_resource_offset) { |
248 return %ScriptPositionInfo(this, position, !!include_resource_offset); | 269 var line = this.lineFromPosition(position); |
| 270 if (line == -1) return null; |
| 271 |
| 272 // Determine start, end and column. |
| 273 var line_ends = this.line_ends; |
| 274 var start = line == 0 ? 0 : line_ends[line - 1] + 1; |
| 275 var end = line_ends[line]; |
| 276 if (end > 0 && %_StringCharAt(this.source, end - 1) === '\r') { |
| 277 end--; |
| 278 } |
| 279 var column = position - start; |
| 280 |
| 281 // Adjust according to the offset within the resource. |
| 282 if (include_resource_offset) { |
| 283 line += this.line_offset; |
| 284 if (line == this.line_offset) { |
| 285 column += this.column_offset; |
| 286 } |
| 287 } |
| 288 |
| 289 return new SourceLocation(this, position, line, column, start, end); |
249 } | 290 } |
250 | 291 |
251 | 292 |
252 /** | 293 /** |
253 * Get information on a specific source line and column possibly offset by a | 294 * Get information on a specific source line and column possibly offset by a |
254 * fixed source position. This function is used to find a source position from | 295 * fixed source position. This function is used to find a source position from |
255 * a line and column position. The fixed source position offset is typically | 296 * a line and column position. The fixed source position offset is typically |
256 * used to find a source position in a function based on a line and column in | 297 * used to find a source position in a function based on a line and column in |
257 * the source for the function alone. The offset passed will then be the | 298 * the source for the function alone. The offset passed will then be the |
258 * start position of the source for the function within the full script source. | 299 * start position of the source for the function within the full script source. |
259 * @param {number} opt_line The line within the source. Default value is 0 | 300 * @param {number} opt_line The line within the source. Default value is 0 |
260 * @param {number} opt_column The column in within the line. Default value is 0 | 301 * @param {number} opt_column The column in within the line. Default value is 0 |
261 * @param {number} opt_offset_position The offset from the begining of the | 302 * @param {number} opt_offset_position The offset from the begining of the |
262 * source from where the line and column calculation starts. | 303 * source from where the line and column calculation starts. |
263 * Default value is 0 | 304 * Default value is 0 |
264 * @return If line is negative or not in the source null is returned. | 305 * @return {SourceLocation} |
| 306 * If line is negative or not in the source null is returned. |
265 */ | 307 */ |
266 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) { | 308 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) { |
267 // Default is the first line in the script. Lines in the script is relative | 309 // Default is the first line in the script. Lines in the script is relative |
268 // to the offset within the resource. | 310 // to the offset within the resource. |
269 var line = 0; | 311 var line = 0; |
270 if (!IS_UNDEFINED(opt_line)) { | 312 if (!IS_UNDEFINED(opt_line)) { |
271 line = opt_line - this.line_offset; | 313 line = opt_line - this.line_offset; |
272 } | 314 } |
273 | 315 |
274 // Default is first column. If on the first line add the offset within the | 316 // Default is first column. If on the first line add the offset within the |
275 // resource. | 317 // resource. |
276 var column = opt_column || 0; | 318 var column = opt_column || 0; |
277 if (line == 0) { | 319 if (line == 0) { |
278 column -= this.column_offset; | 320 column -= this.column_offset; |
279 } | 321 } |
280 | 322 |
281 var offset_position = opt_offset_position || 0; | 323 var offset_position = opt_offset_position || 0; |
282 if (line < 0 || column < 0 || offset_position < 0) return null; | 324 if (line < 0 || column < 0 || offset_position < 0) return null; |
283 if (line == 0) { | 325 if (line == 0) { |
284 return this.locationFromPosition(offset_position + column, false); | 326 return this.locationFromPosition(offset_position + column, false); |
285 } else { | 327 } else { |
286 // Find the line where the offset position is located. | 328 // Find the line where the offset position is located. |
287 var offset_line = this.lineFromPosition(offset_position); | 329 var offset_line = this.lineFromPosition(offset_position); |
288 | 330 |
289 if (offset_line == -1 || offset_line + line >= this.lineCount()) { | 331 if (offset_line == -1 || offset_line + line >= this.lineCount()) { |
290 return null; | 332 return null; |
291 } | 333 } |
292 | 334 |
293 return this.locationFromPosition( | 335 return this.locationFromPosition( |
294 %ScriptLineStartPosition(this, offset_line + line) + column); | 336 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here. |
295 } | 337 } |
296 } | 338 } |
297 | 339 |
298 | 340 |
299 /** | 341 /** |
300 * Get a slice of source code from the script. The boundaries for the slice is | 342 * Get a slice of source code from the script. The boundaries for the slice is |
301 * specified in lines. | 343 * specified in lines. |
302 * @param {number} opt_from_line The first line (zero bound) in the slice. | 344 * @param {number} opt_from_line The first line (zero bound) in the slice. |
303 * Default is 0 | 345 * Default is 0 |
304 * @param {number} opt_to_column The last line (zero bound) in the slice (non | 346 * @param {number} opt_to_column The last line (zero bound) in the slice (non |
(...skipping 13 matching lines...) Expand all Loading... |
318 if (from_line < 0) from_line = 0; | 360 if (from_line < 0) from_line = 0; |
319 if (to_line > this.lineCount()) to_line = this.lineCount(); | 361 if (to_line > this.lineCount()) to_line = this.lineCount(); |
320 | 362 |
321 // Check parameters. | 363 // Check parameters. |
322 if (from_line >= this.lineCount() || | 364 if (from_line >= this.lineCount() || |
323 to_line < 0 || | 365 to_line < 0 || |
324 from_line > to_line) { | 366 from_line > to_line) { |
325 return null; | 367 return null; |
326 } | 368 } |
327 | 369 |
328 var from_position = %ScriptLineStartPosition(this, from_line); | 370 var line_ends = this.line_ends; |
329 var to_position = %ScriptLineStartPosition(this, to_line); | 371 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1; |
| 372 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1; |
330 | 373 |
331 // Return a source slice with line numbers re-adjusted to the resource. | 374 // Return a source slice with line numbers re-adjusted to the resource. |
332 return new SourceSlice(this, | 375 return new SourceSlice(this, |
333 from_line + this.line_offset, | 376 from_line + this.line_offset, |
334 to_line + this.line_offset, | 377 to_line + this.line_offset, |
335 from_position, to_position); | 378 from_position, to_position); |
336 } | 379 } |
337 | 380 |
338 | 381 |
339 function ScriptSourceLine(opt_line) { | 382 function ScriptSourceLine(opt_line) { |
340 // Default is the first line in the script. Lines in the script are relative | 383 // Default is the first line in the script. Lines in the script are relative |
341 // to the offset within the resource. | 384 // to the offset within the resource. |
342 var line = 0; | 385 var line = 0; |
343 if (!IS_UNDEFINED(opt_line)) { | 386 if (!IS_UNDEFINED(opt_line)) { |
344 line = opt_line - this.line_offset; | 387 line = opt_line - this.line_offset; |
345 } | 388 } |
346 | 389 |
347 // Check parameter. | 390 // Check parameter. |
348 if (line < 0 || this.lineCount() <= line) { | 391 if (line < 0 || this.lineCount() <= line) { |
349 return null; | 392 return null; |
350 } | 393 } |
351 | 394 |
352 // Return the source line. | 395 // Return the source line. |
353 var start = %ScriptLineStartPosition(this, line); | 396 var line_ends = this.line_ends; |
354 var end = %ScriptLineEndPosition(this, line); | 397 var start = line == 0 ? 0 : line_ends[line - 1] + 1; |
| 398 var end = line_ends[line]; |
355 return %_Call(StringSubstring, this.source, start, end); | 399 return %_Call(StringSubstring, this.source, start, end); |
356 } | 400 } |
357 | 401 |
358 | 402 |
359 /** | 403 /** |
360 * Returns the number of source lines. | 404 * Returns the number of source lines. |
361 * @return {number} | 405 * @return {number} |
362 * Number of source lines. | 406 * Number of source lines. |
363 */ | 407 */ |
364 function ScriptLineCount() { | 408 function ScriptLineCount() { |
365 // Return number of source lines. | 409 // Return number of source lines. |
366 return %ScriptLineCount(this); | 410 return this.line_ends.length; |
367 } | 411 } |
368 | 412 |
369 | 413 |
| 414 /** |
| 415 * Returns the position of the nth line end. |
| 416 * @return {number} |
| 417 * Zero-based position of the nth line end in the script. |
| 418 */ |
| 419 function ScriptLineEnd(n) { |
| 420 return this.line_ends[n]; |
| 421 } |
| 422 |
| 423 |
370 /** | 424 /** |
371 * If sourceURL comment is available returns sourceURL comment contents. | 425 * If sourceURL comment is available returns sourceURL comment contents. |
372 * Otherwise, script name is returned. See | 426 * Otherwise, script name is returned. See |
373 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt | 427 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt |
374 * and Source Map Revision 3 proposal for details on using //# sourceURL and | 428 * and Source Map Revision 3 proposal for details on using //# sourceURL and |
375 * deprecated //@ sourceURL comment to identify scripts that don't have name. | 429 * deprecated //@ sourceURL comment to identify scripts that don't have name. |
376 * | 430 * |
377 * @return {?string} script name if present, value for //# sourceURL comment or | 431 * @return {?string} script name if present, value for //# sourceURL comment or |
378 * deprecated //@ sourceURL comment otherwise. | 432 * deprecated //@ sourceURL comment otherwise. |
379 */ | 433 */ |
380 function ScriptNameOrSourceURL() { | 434 function ScriptNameOrSourceURL() { |
381 if (this.source_url) return this.source_url; | 435 if (this.source_url) return this.source_url; |
382 return this.name; | 436 return this.name; |
383 } | 437 } |
384 | 438 |
385 | 439 |
386 utils.SetUpLockedPrototype(Script, [ | 440 utils.SetUpLockedPrototype(Script, [ |
387 "source", | 441 "source", |
388 "name", | 442 "name", |
389 "source_url", | 443 "source_url", |
390 "source_mapping_url", | 444 "source_mapping_url", |
| 445 "line_ends", |
391 "line_offset", | 446 "line_offset", |
392 "column_offset" | 447 "column_offset" |
393 ], [ | 448 ], [ |
394 "lineFromPosition", ScriptLineFromPosition, | 449 "lineFromPosition", ScriptLineFromPosition, |
395 "locationFromPosition", ScriptLocationFromPosition, | 450 "locationFromPosition", ScriptLocationFromPosition, |
396 "locationFromLine", ScriptLocationFromLine, | 451 "locationFromLine", ScriptLocationFromLine, |
397 "sourceSlice", ScriptSourceSlice, | 452 "sourceSlice", ScriptSourceSlice, |
398 "sourceLine", ScriptSourceLine, | 453 "sourceLine", ScriptSourceLine, |
399 "lineCount", ScriptLineCount, | 454 "lineCount", ScriptLineCount, |
400 "nameOrSourceURL", ScriptNameOrSourceURL, | 455 "nameOrSourceURL", ScriptNameOrSourceURL, |
| 456 "lineEnd", ScriptLineEnd |
401 ] | 457 ] |
402 ); | 458 ); |
403 | 459 |
404 | 460 |
| 461 /** |
| 462 * Class for source location. A source location is a position within some |
| 463 * source with the following properties: |
| 464 * script : script object for the source |
| 465 * line : source line number |
| 466 * column : source column within the line |
| 467 * position : position within the source |
| 468 * start : position of start of source context (inclusive) |
| 469 * end : position of end of source context (not inclusive) |
| 470 * Source text for the source context is the character interval |
| 471 * [start, end[. In most cases end will point to a newline character. |
| 472 * It might point just past the final position of the source if the last |
| 473 * source line does not end with a newline character. |
| 474 * @param {Script} script The Script object for which this is a location |
| 475 * @param {number} position Source position for the location |
| 476 * @param {number} line The line number for the location |
| 477 * @param {number} column The column within the line for the location |
| 478 * @param {number} start Source position for start of source context |
| 479 * @param {number} end Source position for end of source context |
| 480 * @constructor |
| 481 */ |
| 482 function SourceLocation(script, position, line, column, start, end) { |
| 483 this.script = script; |
| 484 this.position = position; |
| 485 this.line = line; |
| 486 this.column = column; |
| 487 this.start = start; |
| 488 this.end = end; |
| 489 } |
| 490 |
| 491 |
| 492 /** |
| 493 * Get the source text for a SourceLocation |
| 494 * @return {String} |
| 495 * Source text for this location. |
| 496 */ |
| 497 function SourceLocationSourceText() { |
| 498 return %_Call(StringSubstring, this.script.source, this.start, this.end); |
| 499 } |
| 500 |
| 501 |
| 502 utils.SetUpLockedPrototype(SourceLocation, |
| 503 ["script", "position", "line", "column", "start", "end"], |
| 504 ["sourceText", SourceLocationSourceText] |
| 505 ); |
| 506 |
| 507 |
405 /** | 508 /** |
406 * Class for a source slice. A source slice is a part of a script source with | 509 * Class for a source slice. A source slice is a part of a script source with |
407 * the following properties: | 510 * the following properties: |
408 * script : script object for the source | 511 * script : script object for the source |
409 * from_line : line number for the first line in the slice | 512 * from_line : line number for the first line in the slice |
410 * to_line : source line number for the last line in the slice | 513 * to_line : source line number for the last line in the slice |
411 * from_position : position of the first character in the slice | 514 * from_position : position of the first character in the slice |
412 * to_position : position of the last character in the slice | 515 * to_position : position of the last character in the slice |
413 * The to_line and to_position are not included in the slice, that is the lines | 516 * The to_line and to_position are not included in the slice, that is the lines |
414 * in the slice are [from_line, to_line[. Likewise the characters in the slice | 517 * in the slice are [from_line, to_line[. Likewise the characters in the slice |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 utils.Export(function(to) { | 1045 utils.Export(function(to) { |
943 to.ErrorToString = ErrorToString; | 1046 to.ErrorToString = ErrorToString; |
944 to.MakeError = MakeError; | 1047 to.MakeError = MakeError; |
945 to.MakeRangeError = MakeRangeError; | 1048 to.MakeRangeError = MakeRangeError; |
946 to.MakeSyntaxError = MakeSyntaxError; | 1049 to.MakeSyntaxError = MakeSyntaxError; |
947 to.MakeTypeError = MakeTypeError; | 1050 to.MakeTypeError = MakeTypeError; |
948 to.MakeURIError = MakeURIError; | 1051 to.MakeURIError = MakeURIError; |
949 }); | 1052 }); |
950 | 1053 |
951 }); | 1054 }); |
OLD | NEW |