Revert of [simd.js] Update to spec version 0.8.2. (patchset #11 id:200001 of https...
[platform/upstream/v8.git] / 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 $errorToString;
8 var MakeError;
9 var MakeEvalError;
10 var MakeRangeError;
11 var MakeReferenceError;
12 var MakeSyntaxError;
13 var MakeTypeError;
14 var MakeURIError;
15
16 (function(global, utils) {
17
18 %CheckIsBootstrapping();
19
20 // -------------------------------------------------------------------
21 // Imports
22
23 var ArrayJoin;
24 var Bool16x8ToString;
25 var Bool32x4ToString;
26 var Bool8x16ToString;
27 var callSiteReceiverSymbol =
28     utils.GetPrivateSymbol("call_site_receiver_symbol");
29 var callSiteFunctionSymbol =
30     utils.GetPrivateSymbol("call_site_function_symbol");
31 var callSitePositionSymbol =
32     utils.GetPrivateSymbol("call_site_position_symbol");
33 var callSiteStrictSymbol = utils.GetPrivateSymbol("call_site_strict_symbol");
34 var Float32x4ToString;
35 var formattedStackTraceSymbol =
36     utils.GetPrivateSymbol("formatted_stack_trace_symbol");
37 var FunctionSourceString
38 var GlobalObject = global.Object;
39 var Int16x8ToString;
40 var Int32x4ToString;
41 var Int8x16ToString;
42 var InternalArray = utils.InternalArray;
43 var internalErrorSymbol = utils.GetPrivateSymbol("internal_error_symbol");
44 var ObjectDefineProperty;
45 var ObjectToString;
46 var stackTraceSymbol = utils.GetPrivateSymbol("stack_trace_symbol");
47 var StringCharAt;
48 var StringIndexOf;
49 var StringSubstring;
50 var ToString;
51
52 utils.Import(function(from) {
53   ArrayJoin = from.ArrayJoin;
54   Bool16x8ToString = from.Bool16x8ToString;
55   Bool32x4ToString = from.Bool32x4ToString;
56   Bool8x16ToString = from.Bool8x16ToString;
57   Float32x4ToString = from.Float32x4ToString;
58   FunctionSourceString = from.FunctionSourceString;
59   Int16x8ToString = from.Int16x8ToString;
60   Int32x4ToString = from.Int32x4ToString;
61   Int8x16ToString = from.Int8x16ToString;
62   ObjectDefineProperty = from.ObjectDefineProperty;
63   ObjectToString = from.ObjectToString;
64   StringCharAt = from.StringCharAt;
65   StringIndexOf = from.StringIndexOf;
66   StringSubstring = from.StringSubstring;
67 });
68
69 utils.ImportNow(function(from) {
70   ToString = from.ToString;
71 });
72
73 // -------------------------------------------------------------------
74
75 var GlobalError;
76 var GlobalTypeError;
77 var GlobalRangeError;
78 var GlobalURIError;
79 var GlobalSyntaxError;
80 var GlobalReferenceError;
81 var GlobalEvalError;
82
83
84 function NoSideEffectsObjectToString() {
85   if (IS_UNDEFINED(this)) return "[object Undefined]";
86   if (IS_NULL(this)) return "[object Null]";
87   return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
88 }
89
90
91 function NoSideEffectToString(obj) {
92   if (IS_STRING(obj)) return obj;
93   if (IS_NUMBER(obj)) return %_NumberToString(obj);
94   if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
95   if (IS_UNDEFINED(obj)) return 'undefined';
96   if (IS_NULL(obj)) return 'null';
97   if (IS_FUNCTION(obj)) {
98     var str = %_CallFunction(obj, obj, FunctionSourceString);
99     if (str.length > 128) {
100       str = %_SubString(str, 0, 111) + "...<omitted>..." +
101             %_SubString(str, str.length - 2, str.length);
102     }
103     return str;
104   }
105   if (IS_SYMBOL(obj)) return %_CallFunction(obj, $symbolToString);
106   if (IS_SIMD_VALUE(obj)) {
107     switch (typeof(obj)) {
108       case 'float32x4': return %_CallFunction(obj, Float32x4ToString);
109       case 'int32x4':   return %_CallFunction(obj, Int32x4ToString);
110       case 'bool32x4':  return %_CallFunction(obj, Bool32x4ToString);
111       case 'int16x8':   return %_CallFunction(obj, Int16x8ToString);
112       case 'bool16x8':  return %_CallFunction(obj, Bool16x8ToString);
113       case 'int16x8':   return %_CallFunction(obj, Int16x8ToString);
114       case 'bool16x8':  return %_CallFunction(obj, Bool16x8ToString);
115     }
116   }
117   if (IS_OBJECT(obj)
118       && %GetDataProperty(obj, "toString") === ObjectToString) {
119     var constructor = %GetDataProperty(obj, "constructor");
120     if (typeof constructor == "function") {
121       var constructorName = constructor.name;
122       if (IS_STRING(constructorName) && constructorName !== "") {
123         return "#<" + constructorName + ">";
124       }
125     }
126   }
127   if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
128     return %_CallFunction(obj, ErrorToString);
129   }
130
131   return %_CallFunction(obj, NoSideEffectsObjectToString);
132 }
133
134 // To determine whether we can safely stringify an object using ErrorToString
135 // without the risk of side-effects, we need to check whether the object is
136 // either an instance of a native error type (via '%_ClassOf'), or has Error
137 // in its prototype chain and hasn't overwritten 'toString' with something
138 // strange and unusual.
139 function CanBeSafelyTreatedAsAnErrorObject(obj) {
140   switch (%_ClassOf(obj)) {
141     case 'Error':
142     case 'EvalError':
143     case 'RangeError':
144     case 'ReferenceError':
145     case 'SyntaxError':
146     case 'TypeError':
147     case 'URIError':
148       return true;
149   }
150
151   var objToString = %GetDataProperty(obj, "toString");
152   return obj instanceof GlobalError && objToString === ErrorToString;
153 }
154
155
156 // When formatting internally created error messages, do not
157 // invoke overwritten error toString methods but explicitly use
158 // the error to string method. This is to avoid leaking error
159 // objects between script tags in a browser setting.
160 function ToStringCheckErrorObject(obj) {
161   if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
162     return %_CallFunction(obj, ErrorToString);
163   } else {
164     return ToString(obj);
165   }
166 }
167
168
169 function ToDetailString(obj) {
170   if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
171     var constructor = obj.constructor;
172     if (typeof constructor == "function") {
173       var constructorName = constructor.name;
174       if (IS_STRING(constructorName) && constructorName !== "") {
175         return "#<" + constructorName + ">";
176       }
177     }
178   }
179   return ToStringCheckErrorObject(obj);
180 }
181
182
183 function MakeGenericError(constructor, type, arg0, arg1, arg2) {
184   var error = new constructor(FormatMessage(type, arg0, arg1, arg2));
185   error[internalErrorSymbol] = true;
186   return error;
187 }
188
189
190 /**
191  * Set up the Script function and constructor.
192  */
193 %FunctionSetInstanceClassName(Script, 'Script');
194 %AddNamedProperty(Script.prototype, 'constructor', Script,
195                   DONT_ENUM | DONT_DELETE | READ_ONLY);
196 %SetCode(Script, function(x) {
197   // Script objects can only be created by the VM.
198   throw MakeError(kUnsupported);
199 });
200
201
202 // Helper functions; called from the runtime system.
203 function FormatMessage(type, arg0, arg1, arg2) {
204   var arg0 = NoSideEffectToString(arg0);
205   var arg1 = NoSideEffectToString(arg1);
206   var arg2 = NoSideEffectToString(arg2);
207   try {
208     return %FormatMessageString(type, arg0, arg1, arg2);
209   } catch (e) {
210     return "<error>";
211   }
212 }
213
214
215 function GetLineNumber(message) {
216   var start_position = %MessageGetStartPosition(message);
217   if (start_position == -1) return kNoLineNumberInfo;
218   var script = %MessageGetScript(message);
219   var location = script.locationFromPosition(start_position, true);
220   if (location == null) return kNoLineNumberInfo;
221   return location.line + 1;
222 }
223
224
225 //Returns the offset of the given position within the containing line.
226 function GetColumnNumber(message) {
227   var script = %MessageGetScript(message);
228   var start_position = %MessageGetStartPosition(message);
229   var location = script.locationFromPosition(start_position, true);
230   if (location == null) return -1;
231   return location.column;
232 }
233
234
235 // Returns the source code line containing the given source
236 // position, or the empty string if the position is invalid.
237 function GetSourceLine(message) {
238   var script = %MessageGetScript(message);
239   var start_position = %MessageGetStartPosition(message);
240   var location = script.locationFromPosition(start_position, true);
241   if (location == null) return "";
242   return location.sourceText();
243 }
244
245
246 /**
247  * Find a line number given a specific source position.
248  * @param {number} position The source position.
249  * @return {number} 0 if input too small, -1 if input too large,
250        else the line number.
251  */
252 function ScriptLineFromPosition(position) {
253   var lower = 0;
254   var upper = this.lineCount() - 1;
255   var line_ends = this.line_ends;
256
257   // We'll never find invalid positions so bail right away.
258   if (position > line_ends[upper]) {
259     return -1;
260   }
261
262   // This means we don't have to safe-guard indexing line_ends[i - 1].
263   if (position <= line_ends[0]) {
264     return 0;
265   }
266
267   // Binary search to find line # from position range.
268   while (upper >= 1) {
269     var i = (lower + upper) >> 1;
270
271     if (position > line_ends[i]) {
272       lower = i + 1;
273     } else if (position <= line_ends[i - 1]) {
274       upper = i - 1;
275     } else {
276       return i;
277     }
278   }
279
280   return -1;
281 }
282
283 /**
284  * Get information on a specific source position.
285  * @param {number} position The source position
286  * @param {boolean} include_resource_offset Set to true to have the resource
287  *     offset added to the location
288  * @return {SourceLocation}
289  *     If line is negative or not in the source null is returned.
290  */
291 function ScriptLocationFromPosition(position,
292                                     include_resource_offset) {
293   var line = this.lineFromPosition(position);
294   if (line == -1) return null;
295
296   // Determine start, end and column.
297   var line_ends = this.line_ends;
298   var start = line == 0 ? 0 : line_ends[line - 1] + 1;
299   var end = line_ends[line];
300   if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
301     end--;
302   }
303   var column = position - start;
304
305   // Adjust according to the offset within the resource.
306   if (include_resource_offset) {
307     line += this.line_offset;
308     if (line == this.line_offset) {
309       column += this.column_offset;
310     }
311   }
312
313   return new SourceLocation(this, position, line, column, start, end);
314 }
315
316
317 /**
318  * Get information on a specific source line and column possibly offset by a
319  * fixed source position. This function is used to find a source position from
320  * a line and column position. The fixed source position offset is typically
321  * used to find a source position in a function based on a line and column in
322  * the source for the function alone. The offset passed will then be the
323  * start position of the source for the function within the full script source.
324  * @param {number} opt_line The line within the source. Default value is 0
325  * @param {number} opt_column The column in within the line. Default value is 0
326  * @param {number} opt_offset_position The offset from the begining of the
327  *     source from where the line and column calculation starts.
328  *     Default value is 0
329  * @return {SourceLocation}
330  *     If line is negative or not in the source null is returned.
331  */
332 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
333   // Default is the first line in the script. Lines in the script is relative
334   // to the offset within the resource.
335   var line = 0;
336   if (!IS_UNDEFINED(opt_line)) {
337     line = opt_line - this.line_offset;
338   }
339
340   // Default is first column. If on the first line add the offset within the
341   // resource.
342   var column = opt_column || 0;
343   if (line == 0) {
344     column -= this.column_offset;
345   }
346
347   var offset_position = opt_offset_position || 0;
348   if (line < 0 || column < 0 || offset_position < 0) return null;
349   if (line == 0) {
350     return this.locationFromPosition(offset_position + column, false);
351   } else {
352     // Find the line where the offset position is located.
353     var offset_line = this.lineFromPosition(offset_position);
354
355     if (offset_line == -1 || offset_line + line >= this.lineCount()) {
356       return null;
357     }
358
359     return this.locationFromPosition(
360         this.line_ends[offset_line + line - 1] + 1 + column);  // line > 0 here.
361   }
362 }
363
364
365 /**
366  * Get a slice of source code from the script. The boundaries for the slice is
367  * specified in lines.
368  * @param {number} opt_from_line The first line (zero bound) in the slice.
369  *     Default is 0
370  * @param {number} opt_to_column The last line (zero bound) in the slice (non
371  *     inclusive). Default is the number of lines in the script
372  * @return {SourceSlice} The source slice or null of the parameters where
373  *     invalid
374  */
375 function ScriptSourceSlice(opt_from_line, opt_to_line) {
376   var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
377                                               : opt_from_line;
378   var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
379                                           : opt_to_line;
380
381   // Adjust according to the offset within the resource.
382   from_line -= this.line_offset;
383   to_line -= this.line_offset;
384   if (from_line < 0) from_line = 0;
385   if (to_line > this.lineCount()) to_line = this.lineCount();
386
387   // Check parameters.
388   if (from_line >= this.lineCount() ||
389       to_line < 0 ||
390       from_line > to_line) {
391     return null;
392   }
393
394   var line_ends = this.line_ends;
395   var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
396   var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
397
398   // Return a source slice with line numbers re-adjusted to the resource.
399   return new SourceSlice(this,
400                          from_line + this.line_offset,
401                          to_line + this.line_offset,
402                           from_position, to_position);
403 }
404
405
406 function ScriptSourceLine(opt_line) {
407   // Default is the first line in the script. Lines in the script are relative
408   // to the offset within the resource.
409   var line = 0;
410   if (!IS_UNDEFINED(opt_line)) {
411     line = opt_line - this.line_offset;
412   }
413
414   // Check parameter.
415   if (line < 0 || this.lineCount() <= line) {
416     return null;
417   }
418
419   // Return the source line.
420   var line_ends = this.line_ends;
421   var start = line == 0 ? 0 : line_ends[line - 1] + 1;
422   var end = line_ends[line];
423   return %_CallFunction(this.source, start, end, StringSubstring);
424 }
425
426
427 /**
428  * Returns the number of source lines.
429  * @return {number}
430  *     Number of source lines.
431  */
432 function ScriptLineCount() {
433   // Return number of source lines.
434   return this.line_ends.length;
435 }
436
437
438 /**
439  * Returns the position of the nth line end.
440  * @return {number}
441  *     Zero-based position of the nth line end in the script.
442  */
443 function ScriptLineEnd(n) {
444   return this.line_ends[n];
445 }
446
447
448 /**
449  * If sourceURL comment is available returns sourceURL comment contents.
450  * Otherwise, script name is returned. See
451  * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
452  * and Source Map Revision 3 proposal for details on using //# sourceURL and
453  * deprecated //@ sourceURL comment to identify scripts that don't have name.
454  *
455  * @return {?string} script name if present, value for //# sourceURL or
456  * deprecated //@ sourceURL comment otherwise.
457  */
458 function ScriptNameOrSourceURL() {
459   if (this.source_url) return this.source_url;
460   return this.name;
461 }
462
463
464 utils.SetUpLockedPrototype(Script, [
465     "source",
466     "name",
467     "source_url",
468     "source_mapping_url",
469     "line_ends",
470     "line_offset",
471     "column_offset"
472   ], [
473     "lineFromPosition", ScriptLineFromPosition,
474     "locationFromPosition", ScriptLocationFromPosition,
475     "locationFromLine", ScriptLocationFromLine,
476     "sourceSlice", ScriptSourceSlice,
477     "sourceLine", ScriptSourceLine,
478     "lineCount", ScriptLineCount,
479     "nameOrSourceURL", ScriptNameOrSourceURL,
480     "lineEnd", ScriptLineEnd
481   ]
482 );
483
484
485 /**
486  * Class for source location. A source location is a position within some
487  * source with the following properties:
488  *   script   : script object for the source
489  *   line     : source line number
490  *   column   : source column within the line
491  *   position : position within the source
492  *   start    : position of start of source context (inclusive)
493  *   end      : position of end of source context (not inclusive)
494  * Source text for the source context is the character interval
495  * [start, end[. In most cases end will point to a newline character.
496  * It might point just past the final position of the source if the last
497  * source line does not end with a newline character.
498  * @param {Script} script The Script object for which this is a location
499  * @param {number} position Source position for the location
500  * @param {number} line The line number for the location
501  * @param {number} column The column within the line for the location
502  * @param {number} start Source position for start of source context
503  * @param {number} end Source position for end of source context
504  * @constructor
505  */
506 function SourceLocation(script, position, line, column, start, end) {
507   this.script = script;
508   this.position = position;
509   this.line = line;
510   this.column = column;
511   this.start = start;
512   this.end = end;
513 }
514
515
516 /**
517  * Get the source text for a SourceLocation
518  * @return {String}
519  *     Source text for this location.
520  */
521 function SourceLocationSourceText() {
522   return %_CallFunction(this.script.source,
523                         this.start,
524                         this.end,
525                         StringSubstring);
526 }
527
528
529 utils.SetUpLockedPrototype(SourceLocation,
530   ["script", "position", "line", "column", "start", "end"],
531   ["sourceText", SourceLocationSourceText]
532 );
533
534
535 /**
536  * Class for a source slice. A source slice is a part of a script source with
537  * the following properties:
538  *   script        : script object for the source
539  *   from_line     : line number for the first line in the slice
540  *   to_line       : source line number for the last line in the slice
541  *   from_position : position of the first character in the slice
542  *   to_position   : position of the last character in the slice
543  * The to_line and to_position are not included in the slice, that is the lines
544  * in the slice are [from_line, to_line[. Likewise the characters in the slice
545  * are [from_position, to_position[.
546  * @param {Script} script The Script object for the source slice
547  * @param {number} from_line
548  * @param {number} to_line
549  * @param {number} from_position
550  * @param {number} to_position
551  * @constructor
552  */
553 function SourceSlice(script, from_line, to_line, from_position, to_position) {
554   this.script = script;
555   this.from_line = from_line;
556   this.to_line = to_line;
557   this.from_position = from_position;
558   this.to_position = to_position;
559 }
560
561 /**
562  * Get the source text for a SourceSlice
563  * @return {String} Source text for this slice. The last line will include
564  *     the line terminating characters (if any)
565  */
566 function SourceSliceSourceText() {
567   return %_CallFunction(this.script.source,
568                         this.from_position,
569                         this.to_position,
570                         StringSubstring);
571 }
572
573 utils.SetUpLockedPrototype(SourceSlice,
574   ["script", "from_line", "to_line", "from_position", "to_position"],
575   ["sourceText", SourceSliceSourceText]
576 );
577
578
579 function GetStackTraceLine(recv, fun, pos, isGlobal) {
580   return new CallSite(recv, fun, pos, false).toString();
581 }
582
583 // ----------------------------------------------------------------------------
584 // Error implementation
585
586 function CallSite(receiver, fun, pos, strict_mode) {
587   SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
588   SET_PRIVATE(this, callSiteFunctionSymbol, fun);
589   SET_PRIVATE(this, callSitePositionSymbol, pos);
590   SET_PRIVATE(this, callSiteStrictSymbol, strict_mode);
591 }
592
593 function CallSiteGetThis() {
594   return GET_PRIVATE(this, callSiteStrictSymbol)
595       ? UNDEFINED : GET_PRIVATE(this, callSiteReceiverSymbol);
596 }
597
598 function CallSiteGetFunction() {
599   return GET_PRIVATE(this, callSiteStrictSymbol)
600       ? UNDEFINED : GET_PRIVATE(this, callSiteFunctionSymbol);
601 }
602
603 function CallSiteGetPosition() {
604   return GET_PRIVATE(this, callSitePositionSymbol);
605 }
606
607 function CallSiteGetTypeName() {
608   return GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), false);
609 }
610
611 function CallSiteIsToplevel() {
612   return %CallSiteIsToplevelRT(this);
613 }
614
615 function CallSiteIsEval() {
616   return %CallSiteIsEvalRT(this);
617 }
618
619 function CallSiteGetEvalOrigin() {
620   var script = %FunctionGetScript(GET_PRIVATE(this, callSiteFunctionSymbol));
621   return FormatEvalOrigin(script);
622 }
623
624 function CallSiteGetScriptNameOrSourceURL() {
625   return %CallSiteGetScriptNameOrSourceUrlRT(this);
626 }
627
628 function CallSiteGetFunctionName() {
629   // See if the function knows its own name
630   return %CallSiteGetFunctionNameRT(this);
631 }
632
633 function CallSiteGetMethodName() {
634   // See if we can find a unique property on the receiver that holds
635   // this function.
636   return %CallSiteGetMethodNameRT(this);
637 }
638
639 function CallSiteGetFileName() {
640   return %CallSiteGetFileNameRT(this);
641 }
642
643 function CallSiteGetLineNumber() {
644   return %CallSiteGetLineNumberRT(this);
645 }
646
647 function CallSiteGetColumnNumber() {
648   return %CallSiteGetColumnNumberRT(this);
649 }
650
651 function CallSiteIsNative() {
652   return %CallSiteIsNativeRT(this);
653 }
654
655 function CallSiteIsConstructor() {
656   return %CallSiteIsConstructorRT(this);
657 }
658
659 function CallSiteToString() {
660   var fileName;
661   var fileLocation = "";
662   if (this.isNative()) {
663     fileLocation = "native";
664   } else {
665     fileName = this.getScriptNameOrSourceURL();
666     if (!fileName && this.isEval()) {
667       fileLocation = this.getEvalOrigin();
668       fileLocation += ", ";  // Expecting source position to follow.
669     }
670
671     if (fileName) {
672       fileLocation += fileName;
673     } else {
674       // Source code does not originate from a file and is not native, but we
675       // can still get the source position inside the source string, e.g. in
676       // an eval string.
677       fileLocation += "<anonymous>";
678     }
679     var lineNumber = this.getLineNumber();
680     if (lineNumber != null) {
681       fileLocation += ":" + lineNumber;
682       var columnNumber = this.getColumnNumber();
683       if (columnNumber) {
684         fileLocation += ":" + columnNumber;
685       }
686     }
687   }
688
689   var line = "";
690   var functionName = this.getFunctionName();
691   var addSuffix = true;
692   var isConstructor = this.isConstructor();
693   var isMethodCall = !(this.isToplevel() || isConstructor);
694   if (isMethodCall) {
695     var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
696     var methodName = this.getMethodName();
697     if (functionName) {
698       if (typeName &&
699           %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
700         line += typeName + ".";
701       }
702       line += functionName;
703       if (methodName &&
704           (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
705            functionName.length - methodName.length - 1)) {
706         line += " [as " + methodName + "]";
707       }
708     } else {
709       line += typeName + "." + (methodName || "<anonymous>");
710     }
711   } else if (isConstructor) {
712     line += "new " + (functionName || "<anonymous>");
713   } else if (functionName) {
714     line += functionName;
715   } else {
716     line += fileLocation;
717     addSuffix = false;
718   }
719   if (addSuffix) {
720     line += " (" + fileLocation + ")";
721   }
722   return line;
723 }
724
725 utils.SetUpLockedPrototype(CallSite, ["receiver", "fun", "pos"], [
726   "getThis", CallSiteGetThis,
727   "getTypeName", CallSiteGetTypeName,
728   "isToplevel", CallSiteIsToplevel,
729   "isEval", CallSiteIsEval,
730   "getEvalOrigin", CallSiteGetEvalOrigin,
731   "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
732   "getFunction", CallSiteGetFunction,
733   "getFunctionName", CallSiteGetFunctionName,
734   "getMethodName", CallSiteGetMethodName,
735   "getFileName", CallSiteGetFileName,
736   "getLineNumber", CallSiteGetLineNumber,
737   "getColumnNumber", CallSiteGetColumnNumber,
738   "isNative", CallSiteIsNative,
739   "getPosition", CallSiteGetPosition,
740   "isConstructor", CallSiteIsConstructor,
741   "toString", CallSiteToString
742 ]);
743
744
745 function FormatEvalOrigin(script) {
746   var sourceURL = script.nameOrSourceURL();
747   if (sourceURL) {
748     return sourceURL;
749   }
750
751   var eval_origin = "eval at ";
752   if (script.eval_from_function_name) {
753     eval_origin += script.eval_from_function_name;
754   } else {
755     eval_origin +=  "<anonymous>";
756   }
757
758   var eval_from_script = script.eval_from_script;
759   if (eval_from_script) {
760     if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
761       // eval script originated from another eval.
762       eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
763     } else {
764       // eval script originated from "real" source.
765       if (eval_from_script.name) {
766         eval_origin += " (" + eval_from_script.name;
767         var location = eval_from_script.locationFromPosition(
768             script.eval_from_script_position, true);
769         if (location) {
770           eval_origin += ":" + (location.line + 1);
771           eval_origin += ":" + (location.column + 1);
772         }
773         eval_origin += ")";
774       } else {
775         eval_origin += " (unknown source)";
776       }
777     }
778   }
779
780   return eval_origin;
781 }
782
783
784 function FormatErrorString(error) {
785   try {
786     return %_CallFunction(error, ErrorToString);
787   } catch (e) {
788     try {
789       return "<error: " + e + ">";
790     } catch (ee) {
791       return "<error>";
792     }
793   }
794 }
795
796
797 function GetStackFrames(raw_stack) {
798   var frames = new InternalArray();
799   var sloppy_frames = raw_stack[0];
800   for (var i = 1; i < raw_stack.length; i += 4) {
801     var recv = raw_stack[i];
802     var fun = raw_stack[i + 1];
803     var code = raw_stack[i + 2];
804     var pc = raw_stack[i + 3];
805     var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
806     sloppy_frames--;
807     frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
808   }
809   return frames;
810 }
811
812
813 // Flag to prevent recursive call of Error.prepareStackTrace.
814 var formatting_custom_stack_trace = false;
815
816
817 function FormatStackTrace(obj, raw_stack) {
818   var frames = GetStackFrames(raw_stack);
819   if (IS_FUNCTION(GlobalError.prepareStackTrace) &&
820       !formatting_custom_stack_trace) {
821     var array = [];
822     %MoveArrayContents(frames, array);
823     formatting_custom_stack_trace = true;
824     var stack_trace = UNDEFINED;
825     try {
826       stack_trace = GlobalError.prepareStackTrace(obj, array);
827     } catch (e) {
828       throw e;  // The custom formatting function threw.  Rethrow.
829     } finally {
830       formatting_custom_stack_trace = false;
831     }
832     return stack_trace;
833   }
834
835   var lines = new InternalArray();
836   lines.push(FormatErrorString(obj));
837   for (var i = 0; i < frames.length; i++) {
838     var frame = frames[i];
839     var line;
840     try {
841       line = frame.toString();
842     } catch (e) {
843       try {
844         line = "<error: " + e + ">";
845       } catch (ee) {
846         // Any code that reaches this point is seriously nasty!
847         line = "<error>";
848       }
849     }
850     lines.push("    at " + line);
851   }
852   return %_CallFunction(lines, "\n", ArrayJoin);
853 }
854
855
856 function GetTypeName(receiver, requireConstructor) {
857   if (IS_NULL_OR_UNDEFINED(receiver)) return null;
858   var constructor = receiver.constructor;
859   if (!constructor) {
860     return requireConstructor ? null :
861         %_CallFunction(receiver, NoSideEffectsObjectToString);
862   }
863   var constructorName = constructor.name;
864   if (!constructorName) {
865     return requireConstructor ? null :
866         %_CallFunction(receiver, NoSideEffectsObjectToString);
867   }
868   return constructorName;
869 }
870
871
872 // Format the stack trace if not yet done, and return it.
873 // Cache the formatted stack trace on the holder.
874 var StackTraceGetter = function() {
875   var formatted_stack_trace = UNDEFINED;
876   var holder = this;
877   while (holder) {
878     var formatted_stack_trace =
879       GET_PRIVATE(holder, formattedStackTraceSymbol);
880     if (IS_UNDEFINED(formatted_stack_trace)) {
881       // No formatted stack trace available.
882       var stack_trace = GET_PRIVATE(holder, stackTraceSymbol);
883       if (IS_UNDEFINED(stack_trace)) {
884         // Neither formatted nor structured stack trace available.
885         // Look further up the prototype chain.
886         holder = %_GetPrototype(holder);
887         continue;
888       }
889       formatted_stack_trace = FormatStackTrace(holder, stack_trace);
890       SET_PRIVATE(holder, stackTraceSymbol, UNDEFINED);
891       SET_PRIVATE(holder, formattedStackTraceSymbol, formatted_stack_trace);
892     }
893     return formatted_stack_trace;
894   }
895   return UNDEFINED;
896 };
897
898
899 // If the receiver equals the holder, set the formatted stack trace that the
900 // getter returns.
901 var StackTraceSetter = function(v) {
902   if (HAS_PRIVATE(this, stackTraceSymbol)) {
903     SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
904     SET_PRIVATE(this, formattedStackTraceSymbol, v);
905   }
906 };
907
908
909 // Use a dummy function since we do not actually want to capture a stack trace
910 // when constructing the initial Error prototytpes.
911 var captureStackTrace = function() {};
912
913
914 // Define special error type constructors.
915 function DefineError(global, f) {
916   // Store the error function in both the global object
917   // and the runtime object. The function is fetched
918   // from the runtime object when throwing errors from
919   // within the runtime system to avoid strange side
920   // effects when overwriting the error functions from
921   // user code.
922   var name = f.name;
923   %AddNamedProperty(global, name, f, DONT_ENUM);
924   // Configure the error function.
925   if (name == 'Error') {
926     // The prototype of the Error object must itself be an error.
927     // However, it can't be an instance of the Error object because
928     // it hasn't been properly configured yet.  Instead we create a
929     // special not-a-true-error-but-close-enough object.
930     var ErrorPrototype = function() {};
931     %FunctionSetPrototype(ErrorPrototype, GlobalObject.prototype);
932     %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
933     %FunctionSetPrototype(f, new ErrorPrototype());
934   } else {
935     %FunctionSetPrototype(f, new GlobalError());
936     %InternalSetPrototype(f, GlobalError);
937   }
938   %FunctionSetInstanceClassName(f, 'Error');
939   %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
940   %AddNamedProperty(f.prototype, 'name', name, DONT_ENUM);
941   %SetCode(f, function(m) {
942     if (%_IsConstructCall()) {
943       try { captureStackTrace(this, f); } catch (e) { }
944       // Define all the expected properties directly on the error
945       // object. This avoids going through getters and setters defined
946       // on prototype objects.
947       if (!IS_UNDEFINED(m)) {
948         %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM);
949       }
950     } else {
951       return new f(m);
952     }
953   });
954   %SetNativeFlag(f);
955   return f;
956 };
957
958 GlobalError = DefineError(global, function Error() { });
959 GlobalEvalError = DefineError(global, function EvalError() { });
960 GlobalRangeError = DefineError(global, function RangeError() { });
961 GlobalReferenceError = DefineError(global, function ReferenceError() { });
962 GlobalSyntaxError = DefineError(global, function SyntaxError() { });
963 GlobalTypeError = DefineError(global, function TypeError() { });
964 GlobalURIError = DefineError(global, function URIError() { });
965
966 %AddNamedProperty(GlobalError.prototype, 'message', '', DONT_ENUM);
967
968 function ErrorToString() {
969   if (!IS_SPEC_OBJECT(this)) {
970     throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
971   }
972
973   return %ErrorToStringRT(this);
974 }
975
976 utils.InstallFunctions(GlobalError.prototype, DONT_ENUM,
977                        ['toString', ErrorToString]);
978
979 $errorToString = ErrorToString;
980
981 MakeError = function(type, arg0, arg1, arg2) {
982   return MakeGenericError(GlobalError, type, arg0, arg1, arg2);
983 }
984
985 MakeRangeError = function(type, arg0, arg1, arg2) {
986   return MakeGenericError(GlobalRangeError, type, arg0, arg1, arg2);
987 }
988
989 MakeSyntaxError = function(type, arg0, arg1, arg2) {
990   return MakeGenericError(GlobalSyntaxError, type, arg0, arg1, arg2);
991 }
992
993 MakeTypeError = function(type, arg0, arg1, arg2) {
994   return MakeGenericError(GlobalTypeError, type, arg0, arg1, arg2);
995 }
996
997 MakeURIError = function() {
998   return MakeGenericError(GlobalURIError, kURIMalformed);
999 }
1000
1001 // Boilerplate for exceptions for stack overflows. Used from
1002 // Isolate::StackOverflow().
1003 var StackOverflowBoilerplate = MakeRangeError(kStackOverflow);
1004 %DefineAccessorPropertyUnchecked(StackOverflowBoilerplate, 'stack',
1005                                  StackTraceGetter, StackTraceSetter,
1006                                  DONT_ENUM);
1007
1008 // Define actual captureStackTrace function after everything has been set up.
1009 captureStackTrace = function captureStackTrace(obj, cons_opt) {
1010   // Define accessors first, as this may fail and throw.
1011   ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
1012                                        set: StackTraceSetter,
1013                                        configurable: true });
1014   %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
1015 };
1016
1017 GlobalError.captureStackTrace = captureStackTrace;
1018
1019 utils.ExportToRuntime(function(to) {
1020   to["error_function"] = GlobalError;
1021   to["eval_error_function"] = GlobalEvalError;
1022   to["get_stack_trace_line_fun"] = GetStackTraceLine;
1023   to["make_error_function"] = MakeGenericError;
1024   to["message_get_column_number"] = GetColumnNumber;
1025   to["message_get_line_number"] = GetLineNumber;
1026   to["message_get_source_line"] = GetSourceLine;
1027   to["no_side_effect_to_string_fun"] = NoSideEffectToString;
1028   to["range_error_function"] = GlobalRangeError;
1029   to["reference_error_function"] = GlobalReferenceError;
1030   to["stack_overflow_boilerplate"] = StackOverflowBoilerplate;
1031   to["syntax_error_function"] = GlobalSyntaxError;
1032   to["to_detail_string_fun"] = ToDetailString;
1033   to["type_error_function"] = GlobalTypeError;
1034   to["uri_error_function"] = GlobalURIError;
1035 });
1036
1037 });