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