Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / messages.js
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();