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.
5 // -------------------------------------------------------------------
11 var MakeReferenceError;
16 (function(global, utils) {
18 %CheckIsBootstrapping();
20 // -------------------------------------------------------------------
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;
42 var InternalArray = utils.InternalArray;
43 var internalErrorSymbol = utils.GetPrivateSymbol("internal_error_symbol");
44 var ObjectDefineProperty;
46 var stackTraceSymbol = utils.GetPrivateSymbol("stack_trace_symbol");
51 var Float32x4ToString;
62 utils.Import(function(from) {
63 ArrayJoin = from.ArrayJoin;
64 Bool16x8ToString = from.Bool16x8ToString;
65 Bool32x4ToString = from.Bool32x4ToString;
66 Bool8x16ToString = from.Bool8x16ToString;
67 Float32x4ToString = from.Float32x4ToString;
68 FunctionSourceString = from.FunctionSourceString;
69 Int16x8ToString = from.Int16x8ToString;
70 Int32x4ToString = from.Int32x4ToString;
71 Int8x16ToString = from.Int8x16ToString;
72 ObjectDefineProperty = from.ObjectDefineProperty;
73 ObjectToString = from.ObjectToString;
74 StringCharAt = from.StringCharAt;
75 StringIndexOf = from.StringIndexOf;
76 StringSubstring = from.StringSubstring;
77 Float32x4ToString = from.Float32x4ToString;
78 Int32x4ToString = from.Int32x4ToString;
79 Uint32x4ToString = from.Uint32x4ToString;
80 Bool32x4ToString = from.Bool32x4ToString;
81 Int16x8ToString = from.Int16x8ToString;
82 Uint16x8ToString = from.Uint16x8ToString;
83 Bool16x8ToString = from.Bool16x8ToString;
84 Int8x16ToString = from.Int8x16ToString;
85 Uint8x16ToString = from.Uint8x16ToString;
86 Bool8x16ToString = from.Bool8x16ToString;
89 utils.ImportNow(function(from) {
90 ToString = from.ToString;
93 // -------------------------------------------------------------------
99 var GlobalSyntaxError;
100 var GlobalReferenceError;
104 function NoSideEffectsObjectToString() {
105 if (IS_UNDEFINED(this)) return "[object Undefined]";
106 if (IS_NULL(this)) return "[object Null]";
107 return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
111 function NoSideEffectToString(obj) {
112 if (IS_STRING(obj)) return obj;
113 if (IS_NUMBER(obj)) return %_NumberToString(obj);
114 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
115 if (IS_UNDEFINED(obj)) return 'undefined';
116 if (IS_NULL(obj)) return 'null';
117 if (IS_FUNCTION(obj)) {
118 var str = %_CallFunction(obj, obj, FunctionSourceString);
119 if (str.length > 128) {
120 str = %_SubString(str, 0, 111) + "...<omitted>..." +
121 %_SubString(str, str.length - 2, str.length);
125 if (IS_SYMBOL(obj)) return %_CallFunction(obj, $symbolToString);
126 if (IS_SIMD_VALUE(obj)) {
127 switch (typeof(obj)) {
128 case 'float32x4': return %_CallFunction(obj, Float32x4ToString);
129 case 'int32x4': return %_CallFunction(obj, Int32x4ToString);
130 case 'uint32x4': return %_CallFunction(obj, Uint32x4ToString);
131 case 'bool32x4': return %_CallFunction(obj, Bool32x4ToString);
132 case 'int16x8': return %_CallFunction(obj, Int16x8ToString);
133 case 'uint16x8': return %_CallFunction(obj, Uint16x8ToString);
134 case 'bool16x8': return %_CallFunction(obj, Bool16x8ToString);
135 case 'int8x16': return %_CallFunction(obj, Int8x16ToString);
136 case 'uint8x16': return %_CallFunction(obj, Uint8x16ToString);
137 case 'bool8x16': return %_CallFunction(obj, Bool8x16ToString);
141 && %GetDataProperty(obj, "toString") === ObjectToString) {
142 var constructor = %GetDataProperty(obj, "constructor");
143 if (typeof constructor == "function") {
144 var constructorName = constructor.name;
145 if (IS_STRING(constructorName) && constructorName !== "") {
146 return "#<" + constructorName + ">";
150 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
151 return %_CallFunction(obj, ErrorToString);
154 return %_CallFunction(obj, NoSideEffectsObjectToString);
157 // To determine whether we can safely stringify an object using ErrorToString
158 // without the risk of side-effects, we need to check whether the object is
159 // either an instance of a native error type (via '%_ClassOf'), or has Error
160 // in its prototype chain and hasn't overwritten 'toString' with something
161 // strange and unusual.
162 function CanBeSafelyTreatedAsAnErrorObject(obj) {
163 switch (%_ClassOf(obj)) {
167 case 'ReferenceError':
174 var objToString = %GetDataProperty(obj, "toString");
175 return obj instanceof GlobalError && objToString === ErrorToString;
179 // When formatting internally created error messages, do not
180 // invoke overwritten error toString methods but explicitly use
181 // the error to string method. This is to avoid leaking error
182 // objects between script tags in a browser setting.
183 function ToStringCheckErrorObject(obj) {
184 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
185 return %_CallFunction(obj, ErrorToString);
187 return ToString(obj);
192 function ToDetailString(obj) {
193 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
194 var constructor = obj.constructor;
195 if (typeof constructor == "function") {
196 var constructorName = constructor.name;
197 if (IS_STRING(constructorName) && constructorName !== "") {
198 return "#<" + constructorName + ">";
202 return ToStringCheckErrorObject(obj);
206 function MakeGenericError(constructor, type, arg0, arg1, arg2) {
207 var error = new constructor(FormatMessage(type, arg0, arg1, arg2));
208 error[internalErrorSymbol] = true;
214 * Set up the Script function and constructor.
216 %FunctionSetInstanceClassName(Script, 'Script');
217 %AddNamedProperty(Script.prototype, 'constructor', Script,
218 DONT_ENUM | DONT_DELETE | READ_ONLY);
219 %SetCode(Script, function(x) {
220 // Script objects can only be created by the VM.
221 throw MakeError(kUnsupported);
225 // Helper functions; called from the runtime system.
226 function FormatMessage(type, arg0, arg1, arg2) {
227 var arg0 = NoSideEffectToString(arg0);
228 var arg1 = NoSideEffectToString(arg1);
229 var arg2 = NoSideEffectToString(arg2);
231 return %FormatMessageString(type, arg0, arg1, arg2);
238 function GetLineNumber(message) {
239 var start_position = %MessageGetStartPosition(message);
240 if (start_position == -1) return kNoLineNumberInfo;
241 var script = %MessageGetScript(message);
242 var location = script.locationFromPosition(start_position, true);
243 if (location == null) return kNoLineNumberInfo;
244 return location.line + 1;
248 //Returns the offset of the given position within the containing line.
249 function GetColumnNumber(message) {
250 var script = %MessageGetScript(message);
251 var start_position = %MessageGetStartPosition(message);
252 var location = script.locationFromPosition(start_position, true);
253 if (location == null) return -1;
254 return location.column;
258 // Returns the source code line containing the given source
259 // position, or the empty string if the position is invalid.
260 function GetSourceLine(message) {
261 var script = %MessageGetScript(message);
262 var start_position = %MessageGetStartPosition(message);
263 var location = script.locationFromPosition(start_position, true);
264 if (location == null) return "";
265 return location.sourceText();
270 * Find a line number given a specific source position.
271 * @param {number} position The source position.
272 * @return {number} 0 if input too small, -1 if input too large,
273 else the line number.
275 function ScriptLineFromPosition(position) {
277 var upper = this.lineCount() - 1;
278 var line_ends = this.line_ends;
280 // We'll never find invalid positions so bail right away.
281 if (position > line_ends[upper]) {
285 // This means we don't have to safe-guard indexing line_ends[i - 1].
286 if (position <= line_ends[0]) {
290 // Binary search to find line # from position range.
292 var i = (lower + upper) >> 1;
294 if (position > line_ends[i]) {
296 } else if (position <= line_ends[i - 1]) {
307 * Get information on a specific source position.
308 * @param {number} position The source position
309 * @param {boolean} include_resource_offset Set to true to have the resource
310 * offset added to the location
311 * @return {SourceLocation}
312 * If line is negative or not in the source null is returned.
314 function ScriptLocationFromPosition(position,
315 include_resource_offset) {
316 var line = this.lineFromPosition(position);
317 if (line == -1) return null;
319 // Determine start, end and column.
320 var line_ends = this.line_ends;
321 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
322 var end = line_ends[line];
323 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
326 var column = position - start;
328 // Adjust according to the offset within the resource.
329 if (include_resource_offset) {
330 line += this.line_offset;
331 if (line == this.line_offset) {
332 column += this.column_offset;
336 return new SourceLocation(this, position, line, column, start, end);
341 * Get information on a specific source line and column possibly offset by a
342 * fixed source position. This function is used to find a source position from
343 * a line and column position. The fixed source position offset is typically
344 * used to find a source position in a function based on a line and column in
345 * the source for the function alone. The offset passed will then be the
346 * start position of the source for the function within the full script source.
347 * @param {number} opt_line The line within the source. Default value is 0
348 * @param {number} opt_column The column in within the line. Default value is 0
349 * @param {number} opt_offset_position The offset from the begining of the
350 * source from where the line and column calculation starts.
352 * @return {SourceLocation}
353 * If line is negative or not in the source null is returned.
355 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
356 // Default is the first line in the script. Lines in the script is relative
357 // to the offset within the resource.
359 if (!IS_UNDEFINED(opt_line)) {
360 line = opt_line - this.line_offset;
363 // Default is first column. If on the first line add the offset within the
365 var column = opt_column || 0;
367 column -= this.column_offset;
370 var offset_position = opt_offset_position || 0;
371 if (line < 0 || column < 0 || offset_position < 0) return null;
373 return this.locationFromPosition(offset_position + column, false);
375 // Find the line where the offset position is located.
376 var offset_line = this.lineFromPosition(offset_position);
378 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
382 return this.locationFromPosition(
383 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
389 * Get a slice of source code from the script. The boundaries for the slice is
390 * specified in lines.
391 * @param {number} opt_from_line The first line (zero bound) in the slice.
393 * @param {number} opt_to_column The last line (zero bound) in the slice (non
394 * inclusive). Default is the number of lines in the script
395 * @return {SourceSlice} The source slice or null of the parameters where
398 function ScriptSourceSlice(opt_from_line, opt_to_line) {
399 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
401 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
404 // Adjust according to the offset within the resource.
405 from_line -= this.line_offset;
406 to_line -= this.line_offset;
407 if (from_line < 0) from_line = 0;
408 if (to_line > this.lineCount()) to_line = this.lineCount();
411 if (from_line >= this.lineCount() ||
413 from_line > to_line) {
417 var line_ends = this.line_ends;
418 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
419 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
421 // Return a source slice with line numbers re-adjusted to the resource.
422 return new SourceSlice(this,
423 from_line + this.line_offset,
424 to_line + this.line_offset,
425 from_position, to_position);
429 function ScriptSourceLine(opt_line) {
430 // Default is the first line in the script. Lines in the script are relative
431 // to the offset within the resource.
433 if (!IS_UNDEFINED(opt_line)) {
434 line = opt_line - this.line_offset;
438 if (line < 0 || this.lineCount() <= line) {
442 // Return the source line.
443 var line_ends = this.line_ends;
444 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
445 var end = line_ends[line];
446 return %_CallFunction(this.source, start, end, StringSubstring);
451 * Returns the number of source lines.
453 * Number of source lines.
455 function ScriptLineCount() {
456 // Return number of source lines.
457 return this.line_ends.length;
462 * Returns the position of the nth line end.
464 * Zero-based position of the nth line end in the script.
466 function ScriptLineEnd(n) {
467 return this.line_ends[n];
472 * If sourceURL comment is available returns sourceURL comment contents.
473 * Otherwise, script name is returned. See
474 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
475 * and Source Map Revision 3 proposal for details on using //# sourceURL and
476 * deprecated //@ sourceURL comment to identify scripts that don't have name.
478 * @return {?string} script name if present, value for //# sourceURL or
479 * deprecated //@ sourceURL comment otherwise.
481 function ScriptNameOrSourceURL() {
482 if (this.source_url) return this.source_url;
487 utils.SetUpLockedPrototype(Script, [
491 "source_mapping_url",
496 "lineFromPosition", ScriptLineFromPosition,
497 "locationFromPosition", ScriptLocationFromPosition,
498 "locationFromLine", ScriptLocationFromLine,
499 "sourceSlice", ScriptSourceSlice,
500 "sourceLine", ScriptSourceLine,
501 "lineCount", ScriptLineCount,
502 "nameOrSourceURL", ScriptNameOrSourceURL,
503 "lineEnd", ScriptLineEnd
509 * Class for source location. A source location is a position within some
510 * source with the following properties:
511 * script : script object for the source
512 * line : source line number
513 * column : source column within the line
514 * position : position within the source
515 * start : position of start of source context (inclusive)
516 * end : position of end of source context (not inclusive)
517 * Source text for the source context is the character interval
518 * [start, end[. In most cases end will point to a newline character.
519 * It might point just past the final position of the source if the last
520 * source line does not end with a newline character.
521 * @param {Script} script The Script object for which this is a location
522 * @param {number} position Source position for the location
523 * @param {number} line The line number for the location
524 * @param {number} column The column within the line for the location
525 * @param {number} start Source position for start of source context
526 * @param {number} end Source position for end of source context
529 function SourceLocation(script, position, line, column, start, end) {
530 this.script = script;
531 this.position = position;
533 this.column = column;
540 * Get the source text for a SourceLocation
542 * Source text for this location.
544 function SourceLocationSourceText() {
545 return %_CallFunction(this.script.source,
552 utils.SetUpLockedPrototype(SourceLocation,
553 ["script", "position", "line", "column", "start", "end"],
554 ["sourceText", SourceLocationSourceText]
559 * Class for a source slice. A source slice is a part of a script source with
560 * the following properties:
561 * script : script object for the source
562 * from_line : line number for the first line in the slice
563 * to_line : source line number for the last line in the slice
564 * from_position : position of the first character in the slice
565 * to_position : position of the last character in the slice
566 * The to_line and to_position are not included in the slice, that is the lines
567 * in the slice are [from_line, to_line[. Likewise the characters in the slice
568 * are [from_position, to_position[.
569 * @param {Script} script The Script object for the source slice
570 * @param {number} from_line
571 * @param {number} to_line
572 * @param {number} from_position
573 * @param {number} to_position
576 function SourceSlice(script, from_line, to_line, from_position, to_position) {
577 this.script = script;
578 this.from_line = from_line;
579 this.to_line = to_line;
580 this.from_position = from_position;
581 this.to_position = to_position;
585 * Get the source text for a SourceSlice
586 * @return {String} Source text for this slice. The last line will include
587 * the line terminating characters (if any)
589 function SourceSliceSourceText() {
590 return %_CallFunction(this.script.source,
596 utils.SetUpLockedPrototype(SourceSlice,
597 ["script", "from_line", "to_line", "from_position", "to_position"],
598 ["sourceText", SourceSliceSourceText]
602 function GetStackTraceLine(recv, fun, pos, isGlobal) {
603 return new CallSite(recv, fun, pos, false).toString();
606 // ----------------------------------------------------------------------------
607 // Error implementation
609 function CallSite(receiver, fun, pos, strict_mode) {
610 SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
611 SET_PRIVATE(this, callSiteFunctionSymbol, fun);
612 SET_PRIVATE(this, callSitePositionSymbol, pos);
613 SET_PRIVATE(this, callSiteStrictSymbol, strict_mode);
616 function CallSiteGetThis() {
617 return GET_PRIVATE(this, callSiteStrictSymbol)
618 ? UNDEFINED : GET_PRIVATE(this, callSiteReceiverSymbol);
621 function CallSiteGetFunction() {
622 return GET_PRIVATE(this, callSiteStrictSymbol)
623 ? UNDEFINED : GET_PRIVATE(this, callSiteFunctionSymbol);
626 function CallSiteGetPosition() {
627 return GET_PRIVATE(this, callSitePositionSymbol);
630 function CallSiteGetTypeName() {
631 return GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), false);
634 function CallSiteIsToplevel() {
635 return %CallSiteIsToplevelRT(this);
638 function CallSiteIsEval() {
639 return %CallSiteIsEvalRT(this);
642 function CallSiteGetEvalOrigin() {
643 var script = %FunctionGetScript(GET_PRIVATE(this, callSiteFunctionSymbol));
644 return FormatEvalOrigin(script);
647 function CallSiteGetScriptNameOrSourceURL() {
648 return %CallSiteGetScriptNameOrSourceUrlRT(this);
651 function CallSiteGetFunctionName() {
652 // See if the function knows its own name
653 return %CallSiteGetFunctionNameRT(this);
656 function CallSiteGetMethodName() {
657 // See if we can find a unique property on the receiver that holds
659 return %CallSiteGetMethodNameRT(this);
662 function CallSiteGetFileName() {
663 return %CallSiteGetFileNameRT(this);
666 function CallSiteGetLineNumber() {
667 return %CallSiteGetLineNumberRT(this);
670 function CallSiteGetColumnNumber() {
671 return %CallSiteGetColumnNumberRT(this);
674 function CallSiteIsNative() {
675 return %CallSiteIsNativeRT(this);
678 function CallSiteIsConstructor() {
679 return %CallSiteIsConstructorRT(this);
682 function CallSiteToString() {
684 var fileLocation = "";
685 if (this.isNative()) {
686 fileLocation = "native";
688 fileName = this.getScriptNameOrSourceURL();
689 if (!fileName && this.isEval()) {
690 fileLocation = this.getEvalOrigin();
691 fileLocation += ", "; // Expecting source position to follow.
695 fileLocation += fileName;
697 // Source code does not originate from a file and is not native, but we
698 // can still get the source position inside the source string, e.g. in
700 fileLocation += "<anonymous>";
702 var lineNumber = this.getLineNumber();
703 if (lineNumber != null) {
704 fileLocation += ":" + lineNumber;
705 var columnNumber = this.getColumnNumber();
707 fileLocation += ":" + columnNumber;
713 var functionName = this.getFunctionName();
714 var addSuffix = true;
715 var isConstructor = this.isConstructor();
716 var isMethodCall = !(this.isToplevel() || isConstructor);
718 var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
719 var methodName = this.getMethodName();
722 %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
723 line += typeName + ".";
725 line += functionName;
727 (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
728 functionName.length - methodName.length - 1)) {
729 line += " [as " + methodName + "]";
732 line += typeName + "." + (methodName || "<anonymous>");
734 } else if (isConstructor) {
735 line += "new " + (functionName || "<anonymous>");
736 } else if (functionName) {
737 line += functionName;
739 line += fileLocation;
743 line += " (" + fileLocation + ")";
748 utils.SetUpLockedPrototype(CallSite, ["receiver", "fun", "pos"], [
749 "getThis", CallSiteGetThis,
750 "getTypeName", CallSiteGetTypeName,
751 "isToplevel", CallSiteIsToplevel,
752 "isEval", CallSiteIsEval,
753 "getEvalOrigin", CallSiteGetEvalOrigin,
754 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
755 "getFunction", CallSiteGetFunction,
756 "getFunctionName", CallSiteGetFunctionName,
757 "getMethodName", CallSiteGetMethodName,
758 "getFileName", CallSiteGetFileName,
759 "getLineNumber", CallSiteGetLineNumber,
760 "getColumnNumber", CallSiteGetColumnNumber,
761 "isNative", CallSiteIsNative,
762 "getPosition", CallSiteGetPosition,
763 "isConstructor", CallSiteIsConstructor,
764 "toString", CallSiteToString
768 function FormatEvalOrigin(script) {
769 var sourceURL = script.nameOrSourceURL();
774 var eval_origin = "eval at ";
775 if (script.eval_from_function_name) {
776 eval_origin += script.eval_from_function_name;
778 eval_origin += "<anonymous>";
781 var eval_from_script = script.eval_from_script;
782 if (eval_from_script) {
783 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
784 // eval script originated from another eval.
785 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
787 // eval script originated from "real" source.
788 if (eval_from_script.name) {
789 eval_origin += " (" + eval_from_script.name;
790 var location = eval_from_script.locationFromPosition(
791 script.eval_from_script_position, true);
793 eval_origin += ":" + (location.line + 1);
794 eval_origin += ":" + (location.column + 1);
798 eval_origin += " (unknown source)";
807 function FormatErrorString(error) {
809 return %_CallFunction(error, ErrorToString);
812 return "<error: " + e + ">";
820 function GetStackFrames(raw_stack) {
821 var frames = new InternalArray();
822 var sloppy_frames = raw_stack[0];
823 for (var i = 1; i < raw_stack.length; i += 4) {
824 var recv = raw_stack[i];
825 var fun = raw_stack[i + 1];
826 var code = raw_stack[i + 2];
827 var pc = raw_stack[i + 3];
828 var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
830 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
836 // Flag to prevent recursive call of Error.prepareStackTrace.
837 var formatting_custom_stack_trace = false;
840 function FormatStackTrace(obj, raw_stack) {
841 var frames = GetStackFrames(raw_stack);
842 if (IS_FUNCTION(GlobalError.prepareStackTrace) &&
843 !formatting_custom_stack_trace) {
845 %MoveArrayContents(frames, array);
846 formatting_custom_stack_trace = true;
847 var stack_trace = UNDEFINED;
849 stack_trace = GlobalError.prepareStackTrace(obj, array);
851 throw e; // The custom formatting function threw. Rethrow.
853 formatting_custom_stack_trace = false;
858 var lines = new InternalArray();
859 lines.push(FormatErrorString(obj));
860 for (var i = 0; i < frames.length; i++) {
861 var frame = frames[i];
864 line = frame.toString();
867 line = "<error: " + e + ">";
869 // Any code that reaches this point is seriously nasty!
873 lines.push(" at " + line);
875 return %_CallFunction(lines, "\n", ArrayJoin);
879 function GetTypeName(receiver, requireConstructor) {
880 if (IS_NULL_OR_UNDEFINED(receiver)) return null;
881 var constructor = receiver.constructor;
883 return requireConstructor ? null :
884 %_CallFunction(receiver, NoSideEffectsObjectToString);
886 var constructorName = constructor.name;
887 if (!constructorName) {
888 return requireConstructor ? null :
889 %_CallFunction(receiver, NoSideEffectsObjectToString);
891 return constructorName;
895 // Format the stack trace if not yet done, and return it.
896 // Cache the formatted stack trace on the holder.
897 var StackTraceGetter = function() {
898 var formatted_stack_trace = UNDEFINED;
901 var formatted_stack_trace =
902 GET_PRIVATE(holder, formattedStackTraceSymbol);
903 if (IS_UNDEFINED(formatted_stack_trace)) {
904 // No formatted stack trace available.
905 var stack_trace = GET_PRIVATE(holder, stackTraceSymbol);
906 if (IS_UNDEFINED(stack_trace)) {
907 // Neither formatted nor structured stack trace available.
908 // Look further up the prototype chain.
909 holder = %_GetPrototype(holder);
912 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
913 SET_PRIVATE(holder, stackTraceSymbol, UNDEFINED);
914 SET_PRIVATE(holder, formattedStackTraceSymbol, formatted_stack_trace);
916 return formatted_stack_trace;
922 // If the receiver equals the holder, set the formatted stack trace that the
924 var StackTraceSetter = function(v) {
925 if (HAS_PRIVATE(this, stackTraceSymbol)) {
926 SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
927 SET_PRIVATE(this, formattedStackTraceSymbol, v);
932 // Use a dummy function since we do not actually want to capture a stack trace
933 // when constructing the initial Error prototytpes.
934 var captureStackTrace = function() {};
937 // Define special error type constructors.
938 function DefineError(global, f) {
939 // Store the error function in both the global object
940 // and the runtime object. The function is fetched
941 // from the runtime object when throwing errors from
942 // within the runtime system to avoid strange side
943 // effects when overwriting the error functions from
946 %AddNamedProperty(global, name, f, DONT_ENUM);
947 // Configure the error function.
948 if (name == 'Error') {
949 // The prototype of the Error object must itself be an error.
950 // However, it can't be an instance of the Error object because
951 // it hasn't been properly configured yet. Instead we create a
952 // special not-a-true-error-but-close-enough object.
953 var ErrorPrototype = function() {};
954 %FunctionSetPrototype(ErrorPrototype, GlobalObject.prototype);
955 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
956 %FunctionSetPrototype(f, new ErrorPrototype());
958 %FunctionSetPrototype(f, new GlobalError());
959 %InternalSetPrototype(f, GlobalError);
961 %FunctionSetInstanceClassName(f, 'Error');
962 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
963 %AddNamedProperty(f.prototype, 'name', name, DONT_ENUM);
964 %SetCode(f, function(m) {
965 if (%_IsConstructCall()) {
966 try { captureStackTrace(this, f); } catch (e) { }
967 // Define all the expected properties directly on the error
968 // object. This avoids going through getters and setters defined
969 // on prototype objects.
970 if (!IS_UNDEFINED(m)) {
971 %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM);
981 GlobalError = DefineError(global, function Error() { });
982 GlobalEvalError = DefineError(global, function EvalError() { });
983 GlobalRangeError = DefineError(global, function RangeError() { });
984 GlobalReferenceError = DefineError(global, function ReferenceError() { });
985 GlobalSyntaxError = DefineError(global, function SyntaxError() { });
986 GlobalTypeError = DefineError(global, function TypeError() { });
987 GlobalURIError = DefineError(global, function URIError() { });
989 %AddNamedProperty(GlobalError.prototype, 'message', '', DONT_ENUM);
991 function ErrorToString() {
992 if (!IS_SPEC_OBJECT(this)) {
993 throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
996 return %ErrorToStringRT(this);
999 utils.InstallFunctions(GlobalError.prototype, DONT_ENUM,
1000 ['toString', ErrorToString]);
1002 $errorToString = ErrorToString;
1004 MakeError = function(type, arg0, arg1, arg2) {
1005 return MakeGenericError(GlobalError, type, arg0, arg1, arg2);
1008 MakeRangeError = function(type, arg0, arg1, arg2) {
1009 return MakeGenericError(GlobalRangeError, type, arg0, arg1, arg2);
1012 MakeSyntaxError = function(type, arg0, arg1, arg2) {
1013 return MakeGenericError(GlobalSyntaxError, type, arg0, arg1, arg2);
1016 MakeTypeError = function(type, arg0, arg1, arg2) {
1017 return MakeGenericError(GlobalTypeError, type, arg0, arg1, arg2);
1020 MakeURIError = function() {
1021 return MakeGenericError(GlobalURIError, kURIMalformed);
1024 // Boilerplate for exceptions for stack overflows. Used from
1025 // Isolate::StackOverflow().
1026 var StackOverflowBoilerplate = MakeRangeError(kStackOverflow);
1027 %DefineAccessorPropertyUnchecked(StackOverflowBoilerplate, 'stack',
1028 StackTraceGetter, StackTraceSetter,
1031 // Define actual captureStackTrace function after everything has been set up.
1032 captureStackTrace = function captureStackTrace(obj, cons_opt) {
1033 // Define accessors first, as this may fail and throw.
1034 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
1035 set: StackTraceSetter,
1036 configurable: true });
1037 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
1040 GlobalError.captureStackTrace = captureStackTrace;
1042 utils.ExportToRuntime(function(to) {
1043 to["error_function"] = GlobalError;
1044 to["eval_error_function"] = GlobalEvalError;
1045 to["get_stack_trace_line_fun"] = GetStackTraceLine;
1046 to["make_error_function"] = MakeGenericError;
1047 to["message_get_column_number"] = GetColumnNumber;
1048 to["message_get_line_number"] = GetLineNumber;
1049 to["message_get_source_line"] = GetSourceLine;
1050 to["no_side_effect_to_string_fun"] = NoSideEffectToString;
1051 to["range_error_function"] = GlobalRangeError;
1052 to["reference_error_function"] = GlobalReferenceError;
1053 to["stack_overflow_boilerplate"] = StackOverflowBoilerplate;
1054 to["syntax_error_function"] = GlobalSyntaxError;
1055 to["to_detail_string_fun"] = ToDetailString;
1056 to["type_error_function"] = GlobalTypeError;
1057 to["uri_error_function"] = GlobalURIError;