Home | History | Annotate | Download | only in src
      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