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