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