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