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 3 // found in the LICENSE file. 4 5 // ------------------------------------------------------------------- 6 7 var kMessages = { 8 // Error 9 cyclic_proto: ["Cyclic __proto__ value"], 10 code_gen_from_strings: ["%0"], 11 constructor_special_method: ["Class constructor may not be an accessor"], 12 generator_running: ["Generator is already running"], 13 generator_finished: ["Generator has already finished"], 14 // TypeError 15 unexpected_token: ["Unexpected token ", "%0"], 16 unexpected_token_number: ["Unexpected number"], 17 unexpected_token_string: ["Unexpected string"], 18 unexpected_token_identifier: ["Unexpected identifier"], 19 unexpected_reserved: ["Unexpected reserved word"], 20 unexpected_strict_reserved: ["Unexpected strict mode reserved word"], 21 unexpected_eos: ["Unexpected end of input"], 22 malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"], 23 unterminated_regexp: ["Invalid regular expression: missing /"], 24 regexp_flags: ["Cannot supply flags when constructing one RegExp from another"], 25 incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"], 26 multiple_defaults_in_switch: ["More than one default clause in switch statement"], 27 newline_after_throw: ["Illegal newline after throw"], 28 label_redeclaration: ["Label '", "%0", "' has already been declared"], 29 var_redeclaration: ["Identifier '", "%0", "' has already been declared"], 30 duplicate_template_property: ["Object template has duplicate property '", "%0", "'"], 31 no_catch_or_finally: ["Missing catch or finally after try"], 32 unknown_label: ["Undefined label '", "%0", "'"], 33 uncaught_exception: ["Uncaught ", "%0"], 34 stack_trace: ["Stack Trace:\n", "%0"], 35 called_non_callable: ["%0", " is not a function"], 36 undefined_method: ["Object ", "%1", " has no method '", "%0", "'"], 37 property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"], 38 cannot_convert_to_primitive: ["Cannot convert object to primitive value"], 39 not_constructor: ["%0", " is not a constructor"], 40 not_defined: ["%0", " is not defined"], 41 non_method: ["'super' is referenced from non-method"], 42 unsupported_super: ["Unsupported reference to 'super'"], 43 non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"], 44 non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"], 45 with_expression: ["%0", " has no properties"], 46 illegal_invocation: ["Illegal invocation"], 47 no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"], 48 apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"], 49 apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"], 50 toMethod_non_function: ["Function.prototype.toMethod was called on ", "%0", ", which is a ", "%1", " and not a function"], 51 toMethod_non_object: ["Function.prototype.toMethod: home object ", "%0", " is not an object"], 52 invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"], 53 instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"], 54 instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"], 55 undefined_or_null_to_object: ["Cannot convert undefined or null to object"], 56 reduce_no_initial: ["Reduce of empty array with no initial value"], 57 getter_must_be_callable: ["Getter must be a function: ", "%0"], 58 setter_must_be_callable: ["Setter must be a function: ", "%0"], 59 value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"], 60 proto_object_or_null: ["Object prototype may only be an Object or null: ", "%0"], 61 property_desc_object: ["Property description must be an object: ", "%0"], 62 redefine_disallowed: ["Cannot redefine property: ", "%0"], 63 define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."], 64 non_extensible_proto: ["%0", " is not extensible"], 65 handler_non_object: ["Proxy.", "%0", " called with non-object as handler"], 66 proto_non_object: ["Proxy.", "%0", " called with non-object as prototype"], 67 trap_function_expected: ["Proxy.", "%0", " called with non-function for '", "%1", "' trap"], 68 handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"], 69 handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"], 70 handler_returned_false: ["Proxy handler ", "%0", " returned false from '", "%1", "' trap"], 71 handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined from '", "%1", "' trap"], 72 proxy_prop_not_configurable: ["Proxy handler ", "%0", " returned non-configurable descriptor for property '", "%2", "' from '", "%1", "' trap"], 73 proxy_non_object_prop_names: ["Trap '", "%1", "' returned non-object ", "%0"], 74 proxy_repeated_prop_name: ["Trap '", "%1", "' returned repeated property name '", "%2", "'"], 75 invalid_weakmap_key: ["Invalid value used as weak map key"], 76 invalid_weakset_value: ["Invalid value used in weak set"], 77 not_date_object: ["this is not a Date object."], 78 observe_non_object: ["Object.", "%0", " cannot ", "%0", " non-object"], 79 observe_non_function: ["Object.", "%0", " cannot deliver to non-function"], 80 observe_callback_frozen: ["Object.observe cannot deliver to a frozen function object"], 81 observe_invalid_accept: ["Object.observe accept must be an array of strings."], 82 observe_type_non_string: ["Invalid changeRecord with non-string 'type' property"], 83 observe_perform_non_string: ["Invalid non-string changeType"], 84 observe_perform_non_function: ["Cannot perform non-function"], 85 observe_notify_non_notifier: ["notify called on non-notifier object"], 86 observe_global_proxy: ["%0", " cannot be called on the global proxy object"], 87 not_typed_array: ["this is not a typed array."], 88 invalid_argument: ["invalid_argument"], 89 data_view_not_array_buffer: ["First argument to DataView constructor must be an ArrayBuffer"], 90 constructor_not_function: ["Constructor ", "%0", " requires 'new'"], 91 not_a_symbol: ["%0", " is not a symbol"], 92 not_a_promise: ["%0", " is not a promise"], 93 resolver_not_a_function: ["Promise resolver ", "%0", " is not a function"], 94 promise_cyclic: ["Chaining cycle detected for promise ", "%0"], 95 array_functions_on_frozen: ["Cannot modify frozen array elements"], 96 array_functions_change_sealed: ["Cannot add/remove sealed array elements"], 97 first_argument_not_regexp: ["First argument to ", "%0", " must not be a regular expression"], 98 not_iterable: ["%0", " is not iterable"], 99 not_an_iterator: ["%0", " is not an iterator"], 100 iterator_result_not_an_object: ["Iterator result ", "%0", " is not an object"], 101 iterator_value_not_an_object: ["Iterator value ", "%0", " is not an entry object"], 102 // RangeError 103 invalid_array_length: ["Invalid array length"], 104 invalid_array_buffer_length: ["Invalid array buffer length"], 105 invalid_string_length: ["Invalid string length"], 106 invalid_typed_array_offset: ["Start offset is too large:"], 107 invalid_typed_array_length: ["Invalid typed array length"], 108 invalid_typed_array_alignment: ["%0", " of ", "%1", " should be a multiple of ", "%2"], 109 typed_array_set_source_too_large: 110 ["Source is too large"], 111 typed_array_set_negative_offset: 112 ["Start offset is negative"], 113 invalid_data_view_offset: ["Start offset is outside the bounds of the buffer"], 114 invalid_data_view_length: ["Invalid data view length"], 115 invalid_data_view_accessor_offset: 116 ["Offset is outside the bounds of the DataView"], 117 118 stack_overflow: ["Maximum call stack size exceeded"], 119 invalid_time_value: ["Invalid time value"], 120 invalid_count_value: ["Invalid count value"], 121 invalid_code_point: ["Invalid code point ", "%0"], 122 // ReferenceError 123 invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"], 124 invalid_lhs_in_for: ["Invalid left-hand side in for-loop"], 125 invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"], 126 invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"], 127 // SyntaxError 128 paren_in_arg_string: ["Function arg string contains parenthesis"], 129 not_isvar: ["builtin %IS_VAR: not a variable"], 130 single_function_literal: ["Single function literal required"], 131 invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"], 132 invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"], 133 illegal_break: ["Illegal break statement"], 134 illegal_continue: ["Illegal continue statement"], 135 illegal_return: ["Illegal return statement"], 136 error_loading_debugger: ["Error loading debugger"], 137 no_input_to_regexp: ["No input to ", "%0"], 138 invalid_json: ["String '", "%0", "' is not valid JSON"], 139 circular_structure: ["Converting circular structure to JSON"], 140 called_on_non_object: ["%0", " called on non-object"], 141 called_on_null_or_undefined: ["%0", " called on null or undefined"], 142 array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"], 143 object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"], 144 illegal_access: ["Illegal access"], 145 static_prototype: ["Classes may not have static property named prototype"], 146 strict_mode_with: ["Strict mode code may not include a with statement"], 147 strict_eval_arguments: ["Unexpected eval or arguments in strict mode"], 148 too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"], 149 too_many_parameters: ["Too many parameters in function definition (only 65535 allowed)"], 150 too_many_variables: ["Too many variables declared (only 4194303 allowed)"], 151 strict_param_dupe: ["Strict mode function may not have duplicate parameter names"], 152 strict_octal_literal: ["Octal literals are not allowed in strict mode."], 153 strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"], 154 accessor_data_property: ["Object literal may not have data and accessor property with the same name"], 155 accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"], 156 strict_delete: ["Delete of an unqualified identifier in strict mode."], 157 strict_delete_property: ["Cannot delete property '", "%0", "' of ", "%1"], 158 strict_const: ["Use of const in strict mode."], 159 strict_function: ["In strict mode code, functions can only be declared at top level or immediately within another function." ], 160 strict_read_only_property: ["Cannot assign to read only property '", "%0", "' of ", "%1"], 161 strict_cannot_assign: ["Cannot assign to read only '", "%0", "' in strict mode"], 162 strict_poison_pill: ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"], 163 strict_caller: ["Illegal access to a strict mode caller function."], 164 malformed_arrow_function_parameter_list: ["Malformed arrow function parameter list"], 165 generator_poison_pill: ["'caller' and 'arguments' properties may not be accessed on generator functions."], 166 unprotected_let: ["Illegal let declaration in unprotected statement context."], 167 unprotected_const: ["Illegal const declaration in unprotected statement context."], 168 cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"], 169 redef_external_array_element: ["Cannot redefine a property of an object with external array elements"], 170 harmony_const_assign: ["Assignment to constant variable."], 171 symbol_to_string: ["Cannot convert a Symbol value to a string"], 172 symbol_to_primitive: ["Cannot convert a Symbol wrapper object to a primitive value"], 173 symbol_to_number: ["Cannot convert a Symbol value to a number"], 174 invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"], 175 module_type_error: ["Module '", "%0", "' used improperly"], 176 module_export_undefined: ["Export '", "%0", "' is not defined in module"], 177 unexpected_super: ["'super' keyword unexpected here"] 178 }; 179 180 181 function FormatString(format, args) { 182 var result = ""; 183 var arg_num = 0; 184 for (var i = 0; i < format.length; i++) { 185 var str = format[i]; 186 if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) { 187 // Two-char string starts with "%". 188 var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0; 189 if (arg_num < 4) { 190 // str is one of %0, %1, %2 or %3. 191 try { 192 str = NoSideEffectToString(args[arg_num]); 193 } catch (e) { 194 if (%IsJSModule(args[arg_num])) 195 str = "module"; 196 else if (IS_SPEC_OBJECT(args[arg_num])) 197 str = "object"; 198 else 199 str = "#<error>"; 200 } 201 } 202 } 203 result += str; 204 } 205 return result; 206 } 207 208 209 function NoSideEffectToString(obj) { 210 if (IS_STRING(obj)) return obj; 211 if (IS_NUMBER(obj)) return %_NumberToString(obj); 212 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false'; 213 if (IS_UNDEFINED(obj)) return 'undefined'; 214 if (IS_NULL(obj)) return 'null'; 215 if (IS_FUNCTION(obj)) { 216 var str = %_CallFunction(obj, FunctionToString); 217 if (str.length > 128) { 218 str = %_SubString(str, 0, 111) + "...<omitted>..." + 219 %_SubString(str, str.length - 2, str.length); 220 } 221 return str; 222 } 223 if (IS_SYMBOL(obj)) return %_CallFunction(obj, SymbolToString); 224 if (IS_OBJECT(obj) && %GetDataProperty(obj, "toString") === ObjectToString) { 225 var constructor = %GetDataProperty(obj, "constructor"); 226 if (typeof constructor == "function") { 227 var constructorName = constructor.name; 228 if (IS_STRING(constructorName) && constructorName !== "") { 229 return "#<" + constructorName + ">"; 230 } 231 } 232 } 233 if (CanBeSafelyTreatedAsAnErrorObject(obj)) { 234 return %_CallFunction(obj, ErrorToString); 235 } 236 return %_CallFunction(obj, ObjectToString); 237 } 238 239 // To determine whether we can safely stringify an object using ErrorToString 240 // without the risk of side-effects, we need to check whether the object is 241 // either an instance of a native error type (via '%_ClassOf'), or has $Error 242 // in its prototype chain and hasn't overwritten 'toString' with something 243 // strange and unusual. 244 function CanBeSafelyTreatedAsAnErrorObject(obj) { 245 switch (%_ClassOf(obj)) { 246 case 'Error': 247 case 'EvalError': 248 case 'RangeError': 249 case 'ReferenceError': 250 case 'SyntaxError': 251 case 'TypeError': 252 case 'URIError': 253 return true; 254 } 255 256 var objToString = %GetDataProperty(obj, "toString"); 257 return obj instanceof $Error && objToString === ErrorToString; 258 } 259 260 261 // When formatting internally created error messages, do not 262 // invoke overwritten error toString methods but explicitly use 263 // the error to string method. This is to avoid leaking error 264 // objects between script tags in a browser setting. 265 function ToStringCheckErrorObject(obj) { 266 if (CanBeSafelyTreatedAsAnErrorObject(obj)) { 267 return %_CallFunction(obj, ErrorToString); 268 } else { 269 return ToString(obj); 270 } 271 } 272 273 274 function ToDetailString(obj) { 275 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) { 276 var constructor = obj.constructor; 277 if (typeof constructor == "function") { 278 var constructorName = constructor.name; 279 if (IS_STRING(constructorName) && constructorName !== "") { 280 return "#<" + constructorName + ">"; 281 } 282 } 283 } 284 return ToStringCheckErrorObject(obj); 285 } 286 287 288 function MakeGenericError(constructor, type, args) { 289 if (IS_UNDEFINED(args)) args = []; 290 return new constructor(FormatMessage(type, args)); 291 } 292 293 294 /** 295 * Set up the Script function and constructor. 296 */ 297 %FunctionSetInstanceClassName(Script, 'Script'); 298 %AddNamedProperty(Script.prototype, 'constructor', Script, 299 DONT_ENUM | DONT_DELETE | READ_ONLY); 300 %SetCode(Script, function(x) { 301 // Script objects can only be created by the VM. 302 throw new $Error("Not supported"); 303 }); 304 305 306 // Helper functions; called from the runtime system. 307 function FormatMessage(type, args) { 308 var format = kMessages[type]; 309 if (!format) return "<unknown message " + type + ">"; 310 return FormatString(format, args); 311 } 312 313 314 function GetLineNumber(message) { 315 var start_position = %MessageGetStartPosition(message); 316 if (start_position == -1) return kNoLineNumberInfo; 317 var script = %MessageGetScript(message); 318 var location = script.locationFromPosition(start_position, true); 319 if (location == null) return kNoLineNumberInfo; 320 return location.line + 1; 321 } 322 323 324 // Returns the source code line containing the given source 325 // position, or the empty string if the position is invalid. 326 function GetSourceLine(message) { 327 var script = %MessageGetScript(message); 328 var start_position = %MessageGetStartPosition(message); 329 var location = script.locationFromPosition(start_position, true); 330 if (location == null) return ""; 331 location.restrict(); 332 return location.sourceText(); 333 } 334 335 336 function MakeTypeError(type, args) { 337 return MakeGenericError($TypeError, type, args); 338 } 339 340 341 function MakeRangeError(type, args) { 342 return MakeGenericError($RangeError, type, args); 343 } 344 345 346 function MakeSyntaxError(type, args) { 347 return MakeGenericError($SyntaxError, type, args); 348 } 349 350 351 function MakeReferenceError(type, args) { 352 return MakeGenericError($ReferenceError, type, args); 353 } 354 355 356 function MakeEvalError(type, args) { 357 return MakeGenericError($EvalError, type, args); 358 } 359 360 361 function MakeError(type, args) { 362 return MakeGenericError($Error, type, args); 363 } 364 365 /** 366 * Find a line number given a specific source position. 367 * @param {number} position The source position. 368 * @return {number} 0 if input too small, -1 if input too large, 369 else the line number. 370 */ 371 function ScriptLineFromPosition(position) { 372 var lower = 0; 373 var upper = this.lineCount() - 1; 374 var line_ends = this.line_ends; 375 376 // We'll never find invalid positions so bail right away. 377 if (position > line_ends[upper]) { 378 return -1; 379 } 380 381 // This means we don't have to safe-guard indexing line_ends[i - 1]. 382 if (position <= line_ends[0]) { 383 return 0; 384 } 385 386 // Binary search to find line # from position range. 387 while (upper >= 1) { 388 var i = (lower + upper) >> 1; 389 390 if (position > line_ends[i]) { 391 lower = i + 1; 392 } else if (position <= line_ends[i - 1]) { 393 upper = i - 1; 394 } else { 395 return i; 396 } 397 } 398 399 return -1; 400 } 401 402 /** 403 * Get information on a specific source position. 404 * @param {number} position The source position 405 * @param {boolean} include_resource_offset Set to true to have the resource 406 * offset added to the location 407 * @return {SourceLocation} 408 * If line is negative or not in the source null is returned. 409 */ 410 function ScriptLocationFromPosition(position, 411 include_resource_offset) { 412 var line = this.lineFromPosition(position); 413 if (line == -1) return null; 414 415 // Determine start, end and column. 416 var line_ends = this.line_ends; 417 var start = line == 0 ? 0 : line_ends[line - 1] + 1; 418 var end = line_ends[line]; 419 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') { 420 end--; 421 } 422 var column = position - start; 423 424 // Adjust according to the offset within the resource. 425 if (include_resource_offset) { 426 line += this.line_offset; 427 if (line == this.line_offset) { 428 column += this.column_offset; 429 } 430 } 431 432 return new SourceLocation(this, position, line, column, start, end); 433 } 434 435 436 /** 437 * Get information on a specific source line and column possibly offset by a 438 * fixed source position. This function is used to find a source position from 439 * a line and column position. The fixed source position offset is typically 440 * used to find a source position in a function based on a line and column in 441 * the source for the function alone. The offset passed will then be the 442 * start position of the source for the function within the full script source. 443 * @param {number} opt_line The line within the source. Default value is 0 444 * @param {number} opt_column The column in within the line. Default value is 0 445 * @param {number} opt_offset_position The offset from the begining of the 446 * source from where the line and column calculation starts. 447 * Default value is 0 448 * @return {SourceLocation} 449 * If line is negative or not in the source null is returned. 450 */ 451 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) { 452 // Default is the first line in the script. Lines in the script is relative 453 // to the offset within the resource. 454 var line = 0; 455 if (!IS_UNDEFINED(opt_line)) { 456 line = opt_line - this.line_offset; 457 } 458 459 // Default is first column. If on the first line add the offset within the 460 // resource. 461 var column = opt_column || 0; 462 if (line == 0) { 463 column -= this.column_offset; 464 } 465 466 var offset_position = opt_offset_position || 0; 467 if (line < 0 || column < 0 || offset_position < 0) return null; 468 if (line == 0) { 469 return this.locationFromPosition(offset_position + column, false); 470 } else { 471 // Find the line where the offset position is located. 472 var offset_line = this.lineFromPosition(offset_position); 473 474 if (offset_line == -1 || offset_line + line >= this.lineCount()) { 475 return null; 476 } 477 478 return this.locationFromPosition( 479 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here. 480 } 481 } 482 483 484 /** 485 * Get a slice of source code from the script. The boundaries for the slice is 486 * specified in lines. 487 * @param {number} opt_from_line The first line (zero bound) in the slice. 488 * Default is 0 489 * @param {number} opt_to_column The last line (zero bound) in the slice (non 490 * inclusive). Default is the number of lines in the script 491 * @return {SourceSlice} The source slice or null of the parameters where 492 * invalid 493 */ 494 function ScriptSourceSlice(opt_from_line, opt_to_line) { 495 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset 496 : opt_from_line; 497 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount() 498 : opt_to_line; 499 500 // Adjust according to the offset within the resource. 501 from_line -= this.line_offset; 502 to_line -= this.line_offset; 503 if (from_line < 0) from_line = 0; 504 if (to_line > this.lineCount()) to_line = this.lineCount(); 505 506 // Check parameters. 507 if (from_line >= this.lineCount() || 508 to_line < 0 || 509 from_line > to_line) { 510 return null; 511 } 512 513 var line_ends = this.line_ends; 514 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1; 515 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1; 516 517 // Return a source slice with line numbers re-adjusted to the resource. 518 return new SourceSlice(this, 519 from_line + this.line_offset, 520 to_line + this.line_offset, 521 from_position, to_position); 522 } 523 524 525 function ScriptSourceLine(opt_line) { 526 // Default is the first line in the script. Lines in the script are relative 527 // to the offset within the resource. 528 var line = 0; 529 if (!IS_UNDEFINED(opt_line)) { 530 line = opt_line - this.line_offset; 531 } 532 533 // Check parameter. 534 if (line < 0 || this.lineCount() <= line) { 535 return null; 536 } 537 538 // Return the source line. 539 var line_ends = this.line_ends; 540 var start = line == 0 ? 0 : line_ends[line - 1] + 1; 541 var end = line_ends[line]; 542 return %_CallFunction(this.source, start, end, StringSubstring); 543 } 544 545 546 /** 547 * Returns the number of source lines. 548 * @return {number} 549 * Number of source lines. 550 */ 551 function ScriptLineCount() { 552 // Return number of source lines. 553 return this.line_ends.length; 554 } 555 556 557 /** 558 * If sourceURL comment is available and script starts at zero returns sourceURL 559 * comment contents. Otherwise, script name is returned. See 560 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt 561 * and Source Map Revision 3 proposal for details on using //# sourceURL and 562 * deprecated //@ sourceURL comment to identify scripts that don't have name. 563 * 564 * @return {?string} script name if present, value for //# sourceURL or 565 * deprecated //@ sourceURL comment otherwise. 566 */ 567 function ScriptNameOrSourceURL() { 568 if (this.line_offset > 0 || this.column_offset > 0) { 569 return this.name; 570 } 571 if (this.source_url) { 572 return this.source_url; 573 } 574 return this.name; 575 } 576 577 578 SetUpLockedPrototype(Script, 579 $Array("source", "name", "source_url", "source_mapping_url", "line_ends", 580 "line_offset", "column_offset"), 581 $Array( 582 "lineFromPosition", ScriptLineFromPosition, 583 "locationFromPosition", ScriptLocationFromPosition, 584 "locationFromLine", ScriptLocationFromLine, 585 "sourceSlice", ScriptSourceSlice, 586 "sourceLine", ScriptSourceLine, 587 "lineCount", ScriptLineCount, 588 "nameOrSourceURL", ScriptNameOrSourceURL 589 ) 590 ); 591 592 593 /** 594 * Class for source location. A source location is a position within some 595 * source with the following properties: 596 * script : script object for the source 597 * line : source line number 598 * column : source column within the line 599 * position : position within the source 600 * start : position of start of source context (inclusive) 601 * end : position of end of source context (not inclusive) 602 * Source text for the source context is the character interval 603 * [start, end[. In most cases end will point to a newline character. 604 * It might point just past the final position of the source if the last 605 * source line does not end with a newline character. 606 * @param {Script} script The Script object for which this is a location 607 * @param {number} position Source position for the location 608 * @param {number} line The line number for the location 609 * @param {number} column The column within the line for the location 610 * @param {number} start Source position for start of source context 611 * @param {number} end Source position for end of source context 612 * @constructor 613 */ 614 function SourceLocation(script, position, line, column, start, end) { 615 this.script = script; 616 this.position = position; 617 this.line = line; 618 this.column = column; 619 this.start = start; 620 this.end = end; 621 } 622 623 var kLineLengthLimit = 78; 624 625 /** 626 * Restrict source location start and end positions to make the source slice 627 * no more that a certain number of characters wide. 628 * @param {number} opt_limit The with limit of the source text with a default 629 * of 78 630 * @param {number} opt_before The number of characters to prefer before the 631 * position with a default value of 10 less that the limit 632 */ 633 function SourceLocationRestrict(opt_limit, opt_before) { 634 // Find the actual limit to use. 635 var limit; 636 var before; 637 if (!IS_UNDEFINED(opt_limit)) { 638 limit = opt_limit; 639 } else { 640 limit = kLineLengthLimit; 641 } 642 if (!IS_UNDEFINED(opt_before)) { 643 before = opt_before; 644 } else { 645 // If no before is specified center for small limits and perfer more source 646 // before the the position that after for longer limits. 647 if (limit <= 20) { 648 before = $floor(limit / 2); 649 } else { 650 before = limit - 10; 651 } 652 } 653 if (before >= limit) { 654 before = limit - 1; 655 } 656 657 // If the [start, end[ interval is too big we restrict 658 // it in one or both ends. We make sure to always produce 659 // restricted intervals of maximum allowed size. 660 if (this.end - this.start > limit) { 661 var start_limit = this.position - before; 662 var end_limit = this.position + limit - before; 663 if (this.start < start_limit && end_limit < this.end) { 664 this.start = start_limit; 665 this.end = end_limit; 666 } else if (this.start < start_limit) { 667 this.start = this.end - limit; 668 } else { 669 this.end = this.start + limit; 670 } 671 } 672 } 673 674 675 /** 676 * Get the source text for a SourceLocation 677 * @return {String} 678 * Source text for this location. 679 */ 680 function SourceLocationSourceText() { 681 return %_CallFunction(this.script.source, 682 this.start, 683 this.end, 684 StringSubstring); 685 } 686 687 688 SetUpLockedPrototype(SourceLocation, 689 $Array("script", "position", "line", "column", "start", "end"), 690 $Array( 691 "restrict", SourceLocationRestrict, 692 "sourceText", SourceLocationSourceText 693 ) 694 ); 695 696 697 /** 698 * Class for a source slice. A source slice is a part of a script source with 699 * the following properties: 700 * script : script object for the source 701 * from_line : line number for the first line in the slice 702 * to_line : source line number for the last line in the slice 703 * from_position : position of the first character in the slice 704 * to_position : position of the last character in the slice 705 * The to_line and to_position are not included in the slice, that is the lines 706 * in the slice are [from_line, to_line[. Likewise the characters in the slice 707 * are [from_position, to_position[. 708 * @param {Script} script The Script object for the source slice 709 * @param {number} from_line 710 * @param {number} to_line 711 * @param {number} from_position 712 * @param {number} to_position 713 * @constructor 714 */ 715 function SourceSlice(script, from_line, to_line, from_position, to_position) { 716 this.script = script; 717 this.from_line = from_line; 718 this.to_line = to_line; 719 this.from_position = from_position; 720 this.to_position = to_position; 721 } 722 723 /** 724 * Get the source text for a SourceSlice 725 * @return {String} Source text for this slice. The last line will include 726 * the line terminating characters (if any) 727 */ 728 function SourceSliceSourceText() { 729 return %_CallFunction(this.script.source, 730 this.from_position, 731 this.to_position, 732 StringSubstring); 733 } 734 735 SetUpLockedPrototype(SourceSlice, 736 $Array("script", "from_line", "to_line", "from_position", "to_position"), 737 $Array("sourceText", SourceSliceSourceText) 738 ); 739 740 741 // Returns the offset of the given position within the containing 742 // line. 743 function GetPositionInLine(message) { 744 var script = %MessageGetScript(message); 745 var start_position = %MessageGetStartPosition(message); 746 var location = script.locationFromPosition(start_position, false); 747 if (location == null) return -1; 748 location.restrict(); 749 return start_position - location.start; 750 } 751 752 753 function GetStackTraceLine(recv, fun, pos, isGlobal) { 754 return new CallSite(recv, fun, pos, false).toString(); 755 } 756 757 // ---------------------------------------------------------------------------- 758 // Error implementation 759 760 var CallSiteReceiverKey = NEW_PRIVATE_OWN("CallSite#receiver"); 761 var CallSiteFunctionKey = NEW_PRIVATE_OWN("CallSite#function"); 762 var CallSitePositionKey = NEW_PRIVATE_OWN("CallSite#position"); 763 var CallSiteStrictModeKey = NEW_PRIVATE_OWN("CallSite#strict_mode"); 764 765 function CallSite(receiver, fun, pos, strict_mode) { 766 SET_PRIVATE(this, CallSiteReceiverKey, receiver); 767 SET_PRIVATE(this, CallSiteFunctionKey, fun); 768 SET_PRIVATE(this, CallSitePositionKey, pos); 769 SET_PRIVATE(this, CallSiteStrictModeKey, strict_mode); 770 } 771 772 function CallSiteGetThis() { 773 return GET_PRIVATE(this, CallSiteStrictModeKey) 774 ? UNDEFINED : GET_PRIVATE(this, CallSiteReceiverKey); 775 } 776 777 function CallSiteGetTypeName() { 778 return GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), false); 779 } 780 781 function CallSiteIsToplevel() { 782 if (GET_PRIVATE(this, CallSiteReceiverKey) == null) { 783 return true; 784 } 785 return IS_GLOBAL(GET_PRIVATE(this, CallSiteReceiverKey)); 786 } 787 788 function CallSiteIsEval() { 789 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 790 return script && script.compilation_type == COMPILATION_TYPE_EVAL; 791 } 792 793 function CallSiteGetEvalOrigin() { 794 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 795 return FormatEvalOrigin(script); 796 } 797 798 function CallSiteGetScriptNameOrSourceURL() { 799 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 800 return script ? script.nameOrSourceURL() : null; 801 } 802 803 function CallSiteGetFunction() { 804 return GET_PRIVATE(this, CallSiteStrictModeKey) 805 ? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey); 806 } 807 808 function CallSiteGetFunctionName() { 809 // See if the function knows its own name 810 var name = GET_PRIVATE(this, CallSiteFunctionKey).name; 811 if (name) { 812 return name; 813 } 814 name = %FunctionGetInferredName(GET_PRIVATE(this, CallSiteFunctionKey)); 815 if (name) { 816 return name; 817 } 818 // Maybe this is an evaluation? 819 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 820 if (script && script.compilation_type == COMPILATION_TYPE_EVAL) { 821 return "eval"; 822 } 823 return null; 824 } 825 826 function CallSiteGetMethodName() { 827 // See if we can find a unique property on the receiver that holds 828 // this function. 829 var receiver = GET_PRIVATE(this, CallSiteReceiverKey); 830 var fun = GET_PRIVATE(this, CallSiteFunctionKey); 831 var ownName = fun.name; 832 if (ownName && receiver && 833 (%_CallFunction(receiver, ownName, ObjectLookupGetter) === fun || 834 %_CallFunction(receiver, ownName, ObjectLookupSetter) === fun || 835 (IS_OBJECT(receiver) && %GetDataProperty(receiver, ownName) === fun))) { 836 // To handle DontEnum properties we guess that the method has 837 // the same name as the function. 838 return ownName; 839 } 840 var name = null; 841 for (var prop in receiver) { 842 if (%_CallFunction(receiver, prop, ObjectLookupGetter) === fun || 843 %_CallFunction(receiver, prop, ObjectLookupSetter) === fun || 844 (IS_OBJECT(receiver) && %GetDataProperty(receiver, prop) === fun)) { 845 // If we find more than one match bail out to avoid confusion. 846 if (name) { 847 return null; 848 } 849 name = prop; 850 } 851 } 852 if (name) { 853 return name; 854 } 855 return null; 856 } 857 858 function CallSiteGetFileName() { 859 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 860 return script ? script.name : null; 861 } 862 863 function CallSiteGetLineNumber() { 864 if (GET_PRIVATE(this, CallSitePositionKey) == -1) { 865 return null; 866 } 867 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 868 var location = null; 869 if (script) { 870 location = script.locationFromPosition( 871 GET_PRIVATE(this, CallSitePositionKey), true); 872 } 873 return location ? location.line + 1 : null; 874 } 875 876 function CallSiteGetColumnNumber() { 877 if (GET_PRIVATE(this, CallSitePositionKey) == -1) { 878 return null; 879 } 880 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 881 var location = null; 882 if (script) { 883 location = script.locationFromPosition( 884 GET_PRIVATE(this, CallSitePositionKey), true); 885 } 886 return location ? location.column + 1: null; 887 } 888 889 function CallSiteIsNative() { 890 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey)); 891 return script ? (script.type == TYPE_NATIVE) : false; 892 } 893 894 function CallSiteGetPosition() { 895 return GET_PRIVATE(this, CallSitePositionKey); 896 } 897 898 function CallSiteIsConstructor() { 899 var receiver = GET_PRIVATE(this, CallSiteReceiverKey); 900 var constructor = (receiver != null && IS_OBJECT(receiver)) 901 ? %GetDataProperty(receiver, "constructor") : null; 902 if (!constructor) return false; 903 return GET_PRIVATE(this, CallSiteFunctionKey) === constructor; 904 } 905 906 function CallSiteToString() { 907 var fileName; 908 var fileLocation = ""; 909 if (this.isNative()) { 910 fileLocation = "native"; 911 } else { 912 fileName = this.getScriptNameOrSourceURL(); 913 if (!fileName && this.isEval()) { 914 fileLocation = this.getEvalOrigin(); 915 fileLocation += ", "; // Expecting source position to follow. 916 } 917 918 if (fileName) { 919 fileLocation += fileName; 920 } else { 921 // Source code does not originate from a file and is not native, but we 922 // can still get the source position inside the source string, e.g. in 923 // an eval string. 924 fileLocation += "<anonymous>"; 925 } 926 var lineNumber = this.getLineNumber(); 927 if (lineNumber != null) { 928 fileLocation += ":" + lineNumber; 929 var columnNumber = this.getColumnNumber(); 930 if (columnNumber) { 931 fileLocation += ":" + columnNumber; 932 } 933 } 934 } 935 936 var line = ""; 937 var functionName = this.getFunctionName(); 938 var addSuffix = true; 939 var isConstructor = this.isConstructor(); 940 var isMethodCall = !(this.isToplevel() || isConstructor); 941 if (isMethodCall) { 942 var typeName = GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), true); 943 var methodName = this.getMethodName(); 944 if (functionName) { 945 if (typeName && 946 %_CallFunction(functionName, typeName, StringIndexOfJS) != 0) { 947 line += typeName + "."; 948 } 949 line += functionName; 950 if (methodName && 951 (%_CallFunction(functionName, "." + methodName, StringIndexOfJS) != 952 functionName.length - methodName.length - 1)) { 953 line += " [as " + methodName + "]"; 954 } 955 } else { 956 line += typeName + "." + (methodName || "<anonymous>"); 957 } 958 } else if (isConstructor) { 959 line += "new " + (functionName || "<anonymous>"); 960 } else if (functionName) { 961 line += functionName; 962 } else { 963 line += fileLocation; 964 addSuffix = false; 965 } 966 if (addSuffix) { 967 line += " (" + fileLocation + ")"; 968 } 969 return line; 970 } 971 972 SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array( 973 "getThis", CallSiteGetThis, 974 "getTypeName", CallSiteGetTypeName, 975 "isToplevel", CallSiteIsToplevel, 976 "isEval", CallSiteIsEval, 977 "getEvalOrigin", CallSiteGetEvalOrigin, 978 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL, 979 "getFunction", CallSiteGetFunction, 980 "getFunctionName", CallSiteGetFunctionName, 981 "getMethodName", CallSiteGetMethodName, 982 "getFileName", CallSiteGetFileName, 983 "getLineNumber", CallSiteGetLineNumber, 984 "getColumnNumber", CallSiteGetColumnNumber, 985 "isNative", CallSiteIsNative, 986 "getPosition", CallSiteGetPosition, 987 "isConstructor", CallSiteIsConstructor, 988 "toString", CallSiteToString 989 )); 990 991 992 function FormatEvalOrigin(script) { 993 var sourceURL = script.nameOrSourceURL(); 994 if (sourceURL) { 995 return sourceURL; 996 } 997 998 var eval_origin = "eval at "; 999 if (script.eval_from_function_name) { 1000 eval_origin += script.eval_from_function_name; 1001 } else { 1002 eval_origin += "<anonymous>"; 1003 } 1004 1005 var eval_from_script = script.eval_from_script; 1006 if (eval_from_script) { 1007 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) { 1008 // eval script originated from another eval. 1009 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")"; 1010 } else { 1011 // eval script originated from "real" source. 1012 if (eval_from_script.name) { 1013 eval_origin += " (" + eval_from_script.name; 1014 var location = eval_from_script.locationFromPosition( 1015 script.eval_from_script_position, true); 1016 if (location) { 1017 eval_origin += ":" + (location.line + 1); 1018 eval_origin += ":" + (location.column + 1); 1019 } 1020 eval_origin += ")"; 1021 } else { 1022 eval_origin += " (unknown source)"; 1023 } 1024 } 1025 } 1026 1027 return eval_origin; 1028 } 1029 1030 1031 function FormatErrorString(error) { 1032 try { 1033 return %_CallFunction(error, ErrorToString); 1034 } catch (e) { 1035 try { 1036 return "<error: " + e + ">"; 1037 } catch (ee) { 1038 return "<error>"; 1039 } 1040 } 1041 } 1042 1043 1044 function GetStackFrames(raw_stack) { 1045 var frames = new InternalArray(); 1046 var sloppy_frames = raw_stack[0]; 1047 for (var i = 1; i < raw_stack.length; i += 4) { 1048 var recv = raw_stack[i]; 1049 var fun = raw_stack[i + 1]; 1050 var code = raw_stack[i + 2]; 1051 var pc = raw_stack[i + 3]; 1052 var pos = %FunctionGetPositionForOffset(code, pc); 1053 sloppy_frames--; 1054 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0))); 1055 } 1056 return frames; 1057 } 1058 1059 1060 // Flag to prevent recursive call of Error.prepareStackTrace. 1061 var formatting_custom_stack_trace = false; 1062 1063 1064 function FormatStackTrace(obj, raw_stack) { 1065 var frames = GetStackFrames(raw_stack); 1066 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) { 1067 var array = []; 1068 %MoveArrayContents(frames, array); 1069 formatting_custom_stack_trace = true; 1070 var stack_trace = UNDEFINED; 1071 try { 1072 stack_trace = $Error.prepareStackTrace(obj, array); 1073 } catch (e) { 1074 throw e; // The custom formatting function threw. Rethrow. 1075 } finally { 1076 formatting_custom_stack_trace = false; 1077 } 1078 return stack_trace; 1079 } 1080 1081 var lines = new InternalArray(); 1082 lines.push(FormatErrorString(obj)); 1083 for (var i = 0; i < frames.length; i++) { 1084 var frame = frames[i]; 1085 var line; 1086 try { 1087 line = frame.toString(); 1088 } catch (e) { 1089 try { 1090 line = "<error: " + e + ">"; 1091 } catch (ee) { 1092 // Any code that reaches this point is seriously nasty! 1093 line = "<error>"; 1094 } 1095 } 1096 lines.push(" at " + line); 1097 } 1098 return %_CallFunction(lines, "\n", ArrayJoin); 1099 } 1100 1101 1102 function GetTypeName(receiver, requireConstructor) { 1103 var constructor = receiver.constructor; 1104 if (!constructor) { 1105 return requireConstructor ? null : 1106 %_CallFunction(receiver, ObjectToString); 1107 } 1108 var constructorName = constructor.name; 1109 if (!constructorName) { 1110 return requireConstructor ? null : 1111 %_CallFunction(receiver, ObjectToString); 1112 } 1113 return constructorName; 1114 } 1115 1116 1117 var stack_trace_symbol; // Set during bootstrapping. 1118 var formatted_stack_trace_symbol = NEW_PRIVATE_OWN("formatted stack trace"); 1119 1120 1121 // Format the stack trace if not yet done, and return it. 1122 // Cache the formatted stack trace on the holder. 1123 var StackTraceGetter = function() { 1124 var formatted_stack_trace = UNDEFINED; 1125 var holder = this; 1126 while (holder) { 1127 var formatted_stack_trace = 1128 GET_PRIVATE(holder, formatted_stack_trace_symbol); 1129 if (IS_UNDEFINED(formatted_stack_trace)) { 1130 // No formatted stack trace available. 1131 var stack_trace = GET_PRIVATE(holder, stack_trace_symbol); 1132 if (IS_UNDEFINED(stack_trace)) { 1133 // Neither formatted nor structured stack trace available. 1134 // Look further up the prototype chain. 1135 holder = %GetPrototype(holder); 1136 continue; 1137 } 1138 formatted_stack_trace = FormatStackTrace(holder, stack_trace); 1139 SET_PRIVATE(holder, stack_trace_symbol, UNDEFINED); 1140 SET_PRIVATE(holder, formatted_stack_trace_symbol, formatted_stack_trace); 1141 } 1142 return formatted_stack_trace; 1143 } 1144 return UNDEFINED; 1145 }; 1146 1147 1148 // If the receiver equals the holder, set the formatted stack trace that the 1149 // getter returns. 1150 var StackTraceSetter = function(v) { 1151 if (HAS_PRIVATE(this, stack_trace_symbol)) { 1152 SET_PRIVATE(this, stack_trace_symbol, UNDEFINED); 1153 SET_PRIVATE(this, formatted_stack_trace_symbol, v); 1154 } 1155 }; 1156 1157 1158 // Use a dummy function since we do not actually want to capture a stack trace 1159 // when constructing the initial Error prototytpes. 1160 var captureStackTrace = function captureStackTrace(obj, cons_opt) { 1161 // Define accessors first, as this may fail and throw. 1162 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter, 1163 set: StackTraceSetter, 1164 configurable: true }); 1165 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace); 1166 } 1167 1168 1169 function SetUpError() { 1170 // Define special error type constructors. 1171 1172 var DefineError = function(f) { 1173 // Store the error function in both the global object 1174 // and the runtime object. The function is fetched 1175 // from the runtime object when throwing errors from 1176 // within the runtime system to avoid strange side 1177 // effects when overwriting the error functions from 1178 // user code. 1179 var name = f.name; 1180 %AddNamedProperty(global, name, f, DONT_ENUM); 1181 %AddNamedProperty(builtins, '$' + name, f, 1182 DONT_ENUM | DONT_DELETE | READ_ONLY); 1183 // Configure the error function. 1184 if (name == 'Error') { 1185 // The prototype of the Error object must itself be an error. 1186 // However, it can't be an instance of the Error object because 1187 // it hasn't been properly configured yet. Instead we create a 1188 // special not-a-true-error-but-close-enough object. 1189 var ErrorPrototype = function() {}; 1190 %FunctionSetPrototype(ErrorPrototype, $Object.prototype); 1191 %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); 1192 %FunctionSetPrototype(f, new ErrorPrototype()); 1193 } else { 1194 %FunctionSetPrototype(f, new $Error()); 1195 } 1196 %FunctionSetInstanceClassName(f, 'Error'); 1197 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM); 1198 %AddNamedProperty(f.prototype, "name", name, DONT_ENUM); 1199 %SetCode(f, function(m) { 1200 if (%_IsConstructCall()) { 1201 // Define all the expected properties directly on the error 1202 // object. This avoids going through getters and setters defined 1203 // on prototype objects. 1204 %AddNamedProperty(this, 'stack', UNDEFINED, DONT_ENUM); 1205 if (!IS_UNDEFINED(m)) { 1206 %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM); 1207 } 1208 try { captureStackTrace(this, f); } catch (e) { } 1209 } else { 1210 return new f(m); 1211 } 1212 }); 1213 %SetNativeFlag(f); 1214 }; 1215 1216 DefineError(function Error() { }); 1217 DefineError(function TypeError() { }); 1218 DefineError(function RangeError() { }); 1219 DefineError(function SyntaxError() { }); 1220 DefineError(function ReferenceError() { }); 1221 DefineError(function EvalError() { }); 1222 DefineError(function URIError() { }); 1223 } 1224 1225 SetUpError(); 1226 1227 $Error.captureStackTrace = captureStackTrace; 1228 1229 %AddNamedProperty($Error.prototype, 'message', '', DONT_ENUM); 1230 1231 // Global list of error objects visited during ErrorToString. This is 1232 // used to detect cycles in error toString formatting. 1233 var visited_errors = new InternalArray(); 1234 var cyclic_error_marker = new $Object(); 1235 1236 function GetPropertyWithoutInvokingMonkeyGetters(error, name) { 1237 var current = error; 1238 // Climb the prototype chain until we find the holder. 1239 while (current && !%HasOwnProperty(current, name)) { 1240 current = %GetPrototype(current); 1241 } 1242 if (IS_NULL(current)) return UNDEFINED; 1243 if (!IS_OBJECT(current)) return error[name]; 1244 // If the property is an accessor on one of the predefined errors that can be 1245 // generated statically by the compiler, don't touch it. This is to address 1246 // http://code.google.com/p/chromium/issues/detail?id=69187 1247 var desc = %GetOwnProperty(current, name); 1248 if (desc && desc[IS_ACCESSOR_INDEX]) { 1249 var isName = name === "name"; 1250 if (current === $ReferenceError.prototype) 1251 return isName ? "ReferenceError" : UNDEFINED; 1252 if (current === $SyntaxError.prototype) 1253 return isName ? "SyntaxError" : UNDEFINED; 1254 if (current === $TypeError.prototype) 1255 return isName ? "TypeError" : UNDEFINED; 1256 } 1257 // Otherwise, read normally. 1258 return error[name]; 1259 } 1260 1261 function ErrorToStringDetectCycle(error) { 1262 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker; 1263 try { 1264 var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name"); 1265 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name); 1266 var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message"); 1267 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message); 1268 if (name === "") return message; 1269 if (message === "") return name; 1270 return name + ": " + message; 1271 } finally { 1272 visited_errors.length = visited_errors.length - 1; 1273 } 1274 } 1275 1276 function ErrorToString() { 1277 if (!IS_SPEC_OBJECT(this)) { 1278 throw MakeTypeError("called_on_non_object", ["Error.prototype.toString"]); 1279 } 1280 1281 try { 1282 return ErrorToStringDetectCycle(this); 1283 } catch(e) { 1284 // If this error message was encountered already return the empty 1285 // string for it instead of recursively formatting it. 1286 if (e === cyclic_error_marker) { 1287 return ''; 1288 } 1289 throw e; 1290 } 1291 } 1292 1293 1294 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); 1295 1296 // Boilerplate for exceptions for stack overflows. Used from 1297 // Isolate::StackOverflow(). 1298 function SetUpStackOverflowBoilerplate() { 1299 var boilerplate = MakeRangeError('stack_overflow', []); 1300 1301 %DefineAccessorPropertyUnchecked( 1302 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM); 1303 1304 return boilerplate; 1305 } 1306 1307 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); 1308