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.ImportNow("call_site_receiver_symbol");
29 var callSiteFunctionSymbol =
30 utils.ImportNow("call_site_function_symbol");
31 var callSitePositionSymbol =
32 utils.ImportNow("call_site_position_symbol");
33 var callSiteStrictSymbol =
34 utils.ImportNow("call_site_strict_symbol");
35 var Float32x4ToString;
36 var formattedStackTraceSymbol =
37 utils.ImportNow("formatted_stack_trace_symbol");
38 var FunctionSourceString
39 var GlobalObject = global.Object;
43 var InternalArray = utils.InternalArray;
44 var internalErrorSymbol = utils.ImportNow("internal_error_symbol");
45 var ObjectDefineProperty;
47 var stackTraceSymbol = utils.ImportNow("stack_trace_symbol");
56 utils.Import(function(from) {
57 ArrayJoin = from.ArrayJoin;
58 Bool16x8ToString = from.Bool16x8ToString;
59 Bool32x4ToString = from.Bool32x4ToString;
60 Bool8x16ToString = from.Bool8x16ToString;
61 Float32x4ToString = from.Float32x4ToString;
62 FunctionSourceString = from.FunctionSourceString;
63 Int16x8ToString = from.Int16x8ToString;
64 Int32x4ToString = from.Int32x4ToString;
65 Int8x16ToString = from.Int8x16ToString;
66 ObjectDefineProperty = from.ObjectDefineProperty;
67 ObjectToString = from.ObjectToString;
68 StringCharAt = from.StringCharAt;
69 StringIndexOf = from.StringIndexOf;
70 StringSubstring = from.StringSubstring;
71 SymbolToString = from.SymbolToString;
72 Uint16x8ToString = from.Uint16x8ToString;
73 Uint32x4ToString = from.Uint32x4ToString;
74 Uint8x16ToString = from.Uint8x16ToString;
77 // -------------------------------------------------------------------
83 var GlobalSyntaxError;
84 var GlobalReferenceError;
88 function NoSideEffectsObjectToString() {
89 if (IS_UNDEFINED(this)) return "[object Undefined]";
90 if (IS_NULL(this)) return "[object Null]";
91 return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
95 function NoSideEffectToString(obj) {
96 if (IS_STRING(obj)) return obj;
97 if (IS_NUMBER(obj)) return %_NumberToString(obj);
98 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
99 if (IS_UNDEFINED(obj)) return 'undefined';
100 if (IS_NULL(obj)) return 'null';
101 if (IS_FUNCTION(obj)) {
102 var str = %_CallFunction(obj, obj, FunctionSourceString);
103 if (str.length > 128) {
104 str = %_SubString(str, 0, 111) + "...<omitted>..." +
105 %_SubString(str, str.length - 2, str.length);
109 if (IS_SYMBOL(obj)) return %_CallFunction(obj, SymbolToString);
110 if (IS_SIMD_VALUE(obj)) {
111 switch (typeof(obj)) {
112 case 'float32x4': return %_CallFunction(obj, Float32x4ToString);
113 case 'int32x4': return %_CallFunction(obj, Int32x4ToString);
114 case 'int16x8': return %_CallFunction(obj, Int16x8ToString);
115 case 'int8x16': return %_CallFunction(obj, Int8x16ToString);
116 case 'uint32x4': return %_CallFunction(obj, Uint32x4ToString);
117 case 'uint16x8': return %_CallFunction(obj, Uint16x8ToString);
118 case 'uint8x16': return %_CallFunction(obj, Uint8x16ToString);
119 case 'bool32x4': return %_CallFunction(obj, Bool32x4ToString);
120 case 'bool16x8': return %_CallFunction(obj, Bool16x8ToString);
121 case 'bool8x16': return %_CallFunction(obj, Bool8x16ToString);
125 && %GetDataProperty(obj, "toString") === ObjectToString) {
126 var constructor = %GetDataProperty(obj, "constructor");
127 if (typeof constructor == "function") {
128 var constructorName = constructor.name;
129 if (IS_STRING(constructorName) && constructorName !== "") {
130 return "#<" + constructorName + ">";
134 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
135 return %_CallFunction(obj, ErrorToString);
138 return %_CallFunction(obj, NoSideEffectsObjectToString);
141 // To determine whether we can safely stringify an object using ErrorToString
142 // without the risk of side-effects, we need to check whether the object is
143 // either an instance of a native error type (via '%_ClassOf'), or has Error
144 // in its prototype chain and hasn't overwritten 'toString' with something
145 // strange and unusual.
146 function CanBeSafelyTreatedAsAnErrorObject(obj) {
147 switch (%_ClassOf(obj)) {
151 case 'ReferenceError':
158 var objToString = %GetDataProperty(obj, "toString");
159 return obj instanceof GlobalError && objToString === ErrorToString;
163 // When formatting internally created error messages, do not
164 // invoke overwritten error toString methods but explicitly use
165 // the error to string method. This is to avoid leaking error
166 // objects between script tags in a browser setting.
167 function ToStringCheckErrorObject(obj) {
168 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
169 return %_CallFunction(obj, ErrorToString);
171 return TO_STRING(obj);
176 function ToDetailString(obj) {
177 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
178 var constructor = obj.constructor;
179 if (typeof constructor == "function") {
180 var constructorName = constructor.name;
181 if (IS_STRING(constructorName) && constructorName !== "") {
182 return "#<" + constructorName + ">";
186 return ToStringCheckErrorObject(obj);
190 function MakeGenericError(constructor, type, arg0, arg1, arg2) {
191 var error = new constructor(FormatMessage(type, arg0, arg1, arg2));
192 error[internalErrorSymbol] = true;
198 * Set up the Script function and constructor.
200 %FunctionSetInstanceClassName(Script, 'Script');
201 %AddNamedProperty(Script.prototype, 'constructor', Script,
202 DONT_ENUM | DONT_DELETE | READ_ONLY);
203 %SetCode(Script, function(x) {
204 // Script objects can only be created by the VM.
205 throw MakeError(kUnsupported);
209 // Helper functions; called from the runtime system.
210 function FormatMessage(type, arg0, arg1, arg2) {
211 var arg0 = NoSideEffectToString(arg0);
212 var arg1 = NoSideEffectToString(arg1);
213 var arg2 = NoSideEffectToString(arg2);
215 return %FormatMessageString(type, arg0, arg1, arg2);
222 function GetLineNumber(message) {
223 var start_position = %MessageGetStartPosition(message);
224 if (start_position == -1) return kNoLineNumberInfo;
225 var script = %MessageGetScript(message);
226 var location = script.locationFromPosition(start_position, true);
227 if (location == null) return kNoLineNumberInfo;
228 return location.line + 1;
232 //Returns the offset of the given position within the containing line.
233 function GetColumnNumber(message) {
234 var script = %MessageGetScript(message);
235 var start_position = %MessageGetStartPosition(message);
236 var location = script.locationFromPosition(start_position, true);
237 if (location == null) return -1;
238 return location.column;
242 // Returns the source code line containing the given source
243 // position, or the empty string if the position is invalid.
244 function GetSourceLine(message) {
245 var script = %MessageGetScript(message);
246 var start_position = %MessageGetStartPosition(message);
247 var location = script.locationFromPosition(start_position, true);
248 if (location == null) return "";
249 return location.sourceText();
254 * Find a line number given a specific source position.
255 * @param {number} position The source position.
256 * @return {number} 0 if input too small, -1 if input too large,
257 else the line number.
259 function ScriptLineFromPosition(position) {
261 var upper = this.lineCount() - 1;
262 var line_ends = this.line_ends;
264 // We'll never find invalid positions so bail right away.
265 if (position > line_ends[upper]) {
269 // This means we don't have to safe-guard indexing line_ends[i - 1].
270 if (position <= line_ends[0]) {
274 // Binary search to find line # from position range.
276 var i = (lower + upper) >> 1;
278 if (position > line_ends[i]) {
280 } else if (position <= line_ends[i - 1]) {
291 * Get information on a specific source position.
292 * @param {number} position The source position
293 * @param {boolean} include_resource_offset Set to true to have the resource
294 * offset added to the location
295 * @return {SourceLocation}
296 * If line is negative or not in the source null is returned.
298 function ScriptLocationFromPosition(position,
299 include_resource_offset) {
300 var line = this.lineFromPosition(position);
301 if (line == -1) return null;
303 // Determine start, end and column.
304 var line_ends = this.line_ends;
305 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
306 var end = line_ends[line];
307 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
310 var column = position - start;
312 // Adjust according to the offset within the resource.
313 if (include_resource_offset) {
314 line += this.line_offset;
315 if (line == this.line_offset) {
316 column += this.column_offset;
320 return new SourceLocation(this, position, line, column, start, end);
325 * Get information on a specific source line and column possibly offset by a
326 * fixed source position. This function is used to find a source position from
327 * a line and column position. The fixed source position offset is typically
328 * used to find a source position in a function based on a line and column in
329 * the source for the function alone. The offset passed will then be the
330 * start position of the source for the function within the full script source.
331 * @param {number} opt_line The line within the source. Default value is 0
332 * @param {number} opt_column The column in within the line. Default value is 0
333 * @param {number} opt_offset_position The offset from the begining of the
334 * source from where the line and column calculation starts.
336 * @return {SourceLocation}
337 * If line is negative or not in the source null is returned.
339 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
340 // Default is the first line in the script. Lines in the script is relative
341 // to the offset within the resource.
343 if (!IS_UNDEFINED(opt_line)) {
344 line = opt_line - this.line_offset;
347 // Default is first column. If on the first line add the offset within the
349 var column = opt_column || 0;
351 column -= this.column_offset;
354 var offset_position = opt_offset_position || 0;
355 if (line < 0 || column < 0 || offset_position < 0) return null;
357 return this.locationFromPosition(offset_position + column, false);
359 // Find the line where the offset position is located.
360 var offset_line = this.lineFromPosition(offset_position);
362 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
366 return this.locationFromPosition(
367 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
373 * Get a slice of source code from the script. The boundaries for the slice is
374 * specified in lines.
375 * @param {number} opt_from_line The first line (zero bound) in the slice.
377 * @param {number} opt_to_column The last line (zero bound) in the slice (non
378 * inclusive). Default is the number of lines in the script
379 * @return {SourceSlice} The source slice or null of the parameters where
382 function ScriptSourceSlice(opt_from_line, opt_to_line) {
383 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
385 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
388 // Adjust according to the offset within the resource.
389 from_line -= this.line_offset;
390 to_line -= this.line_offset;
391 if (from_line < 0) from_line = 0;
392 if (to_line > this.lineCount()) to_line = this.lineCount();
395 if (from_line >= this.lineCount() ||
397 from_line > to_line) {
401 var line_ends = this.line_ends;
402 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
403 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
405 // Return a source slice with line numbers re-adjusted to the resource.
406 return new SourceSlice(this,
407 from_line + this.line_offset,
408 to_line + this.line_offset,
409 from_position, to_position);
413 function ScriptSourceLine(opt_line) {
414 // Default is the first line in the script. Lines in the script are relative
415 // to the offset within the resource.
417 if (!IS_UNDEFINED(opt_line)) {
418 line = opt_line - this.line_offset;
422 if (line < 0 || this.lineCount() <= line) {
426 // Return the source line.
427 var line_ends = this.line_ends;
428 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
429 var end = line_ends[line];
430 return %_CallFunction(this.source, start, end, StringSubstring);
435 * Returns the number of source lines.
437 * Number of source lines.
439 function ScriptLineCount() {
440 // Return number of source lines.
441 return this.line_ends.length;
446 * Returns the position of the nth line end.
448 * Zero-based position of the nth line end in the script.
450 function ScriptLineEnd(n) {
451 return this.line_ends[n];
456 * If sourceURL comment is available returns sourceURL comment contents.
457 * Otherwise, script name is returned. See
458 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
459 * and Source Map Revision 3 proposal for details on using //# sourceURL and
460 * deprecated //@ sourceURL comment to identify scripts that don't have name.
462 * @return {?string} script name if present, value for //# sourceURL or
463 * deprecated //@ sourceURL comment otherwise.
465 function ScriptNameOrSourceURL() {
466 if (this.source_url) return this.source_url;
471 utils.SetUpLockedPrototype(Script, [
475 "source_mapping_url",
480 "lineFromPosition", ScriptLineFromPosition,
481 "locationFromPosition", ScriptLocationFromPosition,
482 "locationFromLine", ScriptLocationFromLine,
483 "sourceSlice", ScriptSourceSlice,
484 "sourceLine", ScriptSourceLine,
485 "lineCount", ScriptLineCount,
486 "nameOrSourceURL", ScriptNameOrSourceURL,
487 "lineEnd", ScriptLineEnd
493 * Class for source location. A source location is a position within some
494 * source with the following properties:
495 * script : script object for the source
496 * line : source line number
497 * column : source column within the line
498 * position : position within the source
499 * start : position of start of source context (inclusive)
500 * end : position of end of source context (not inclusive)
501 * Source text for the source context is the character interval
502 * [start, end[. In most cases end will point to a newline character.
503 * It might point just past the final position of the source if the last
504 * source line does not end with a newline character.
505 * @param {Script} script The Script object for which this is a location
506 * @param {number} position Source position for the location
507 * @param {number} line The line number for the location
508 * @param {number} column The column within the line for the location
509 * @param {number} start Source position for start of source context
510 * @param {number} end Source position for end of source context
513 function SourceLocation(script, position, line, column, start, end) {
514 this.script = script;
515 this.position = position;
517 this.column = column;
524 * Get the source text for a SourceLocation
526 * Source text for this location.
528 function SourceLocationSourceText() {
529 return %_CallFunction(this.script.source,
536 utils.SetUpLockedPrototype(SourceLocation,
537 ["script", "position", "line", "column", "start", "end"],
538 ["sourceText", SourceLocationSourceText]
543 * Class for a source slice. A source slice is a part of a script source with
544 * the following properties:
545 * script : script object for the source
546 * from_line : line number for the first line in the slice
547 * to_line : source line number for the last line in the slice
548 * from_position : position of the first character in the slice
549 * to_position : position of the last character in the slice
550 * The to_line and to_position are not included in the slice, that is the lines
551 * in the slice are [from_line, to_line[. Likewise the characters in the slice
552 * are [from_position, to_position[.
553 * @param {Script} script The Script object for the source slice
554 * @param {number} from_line
555 * @param {number} to_line
556 * @param {number} from_position
557 * @param {number} to_position
560 function SourceSlice(script, from_line, to_line, from_position, to_position) {
561 this.script = script;
562 this.from_line = from_line;
563 this.to_line = to_line;
564 this.from_position = from_position;
565 this.to_position = to_position;
569 * Get the source text for a SourceSlice
570 * @return {String} Source text for this slice. The last line will include
571 * the line terminating characters (if any)
573 function SourceSliceSourceText() {
574 return %_CallFunction(this.script.source,
580 utils.SetUpLockedPrototype(SourceSlice,
581 ["script", "from_line", "to_line", "from_position", "to_position"],
582 ["sourceText", SourceSliceSourceText]
586 function GetStackTraceLine(recv, fun, pos, isGlobal) {
587 return new CallSite(recv, fun, pos, false).toString();
590 // ----------------------------------------------------------------------------
591 // Error implementation
593 function CallSite(receiver, fun, pos, strict_mode) {
594 SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
595 SET_PRIVATE(this, callSiteFunctionSymbol, fun);
596 SET_PRIVATE(this, callSitePositionSymbol, pos);
597 SET_PRIVATE(this, callSiteStrictSymbol, strict_mode);
600 function CallSiteGetThis() {
601 return GET_PRIVATE(this, callSiteStrictSymbol)
602 ? UNDEFINED : GET_PRIVATE(this, callSiteReceiverSymbol);
605 function CallSiteGetFunction() {
606 return GET_PRIVATE(this, callSiteStrictSymbol)
607 ? UNDEFINED : GET_PRIVATE(this, callSiteFunctionSymbol);
610 function CallSiteGetPosition() {
611 return GET_PRIVATE(this, callSitePositionSymbol);
614 function CallSiteGetTypeName() {
615 return GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), false);
618 function CallSiteIsToplevel() {
619 return %CallSiteIsToplevelRT(this);
622 function CallSiteIsEval() {
623 return %CallSiteIsEvalRT(this);
626 function CallSiteGetEvalOrigin() {
627 var script = %FunctionGetScript(GET_PRIVATE(this, callSiteFunctionSymbol));
628 return FormatEvalOrigin(script);
631 function CallSiteGetScriptNameOrSourceURL() {
632 return %CallSiteGetScriptNameOrSourceUrlRT(this);
635 function CallSiteGetFunctionName() {
636 // See if the function knows its own name
637 return %CallSiteGetFunctionNameRT(this);
640 function CallSiteGetMethodName() {
641 // See if we can find a unique property on the receiver that holds
643 return %CallSiteGetMethodNameRT(this);
646 function CallSiteGetFileName() {
647 return %CallSiteGetFileNameRT(this);
650 function CallSiteGetLineNumber() {
651 return %CallSiteGetLineNumberRT(this);
654 function CallSiteGetColumnNumber() {
655 return %CallSiteGetColumnNumberRT(this);
658 function CallSiteIsNative() {
659 return %CallSiteIsNativeRT(this);
662 function CallSiteIsConstructor() {
663 return %CallSiteIsConstructorRT(this);
666 function CallSiteToString() {
668 var fileLocation = "";
669 if (this.isNative()) {
670 fileLocation = "native";
672 fileName = this.getScriptNameOrSourceURL();
673 if (!fileName && this.isEval()) {
674 fileLocation = this.getEvalOrigin();
675 fileLocation += ", "; // Expecting source position to follow.
679 fileLocation += fileName;
681 // Source code does not originate from a file and is not native, but we
682 // can still get the source position inside the source string, e.g. in
684 fileLocation += "<anonymous>";
686 var lineNumber = this.getLineNumber();
687 if (lineNumber != null) {
688 fileLocation += ":" + lineNumber;
689 var columnNumber = this.getColumnNumber();
691 fileLocation += ":" + columnNumber;
697 var functionName = this.getFunctionName();
698 var addSuffix = true;
699 var isConstructor = this.isConstructor();
700 var isMethodCall = !(this.isToplevel() || isConstructor);
702 var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
703 var methodName = this.getMethodName();
706 %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
707 line += typeName + ".";
709 line += functionName;
711 (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
712 functionName.length - methodName.length - 1)) {
713 line += " [as " + methodName + "]";
716 line += typeName + "." + (methodName || "<anonymous>");
718 } else if (isConstructor) {
719 line += "new " + (functionName || "<anonymous>");
720 } else if (functionName) {
721 line += functionName;
723 line += fileLocation;
727 line += " (" + fileLocation + ")";
732 utils.SetUpLockedPrototype(CallSite, ["receiver", "fun", "pos"], [
733 "getThis", CallSiteGetThis,
734 "getTypeName", CallSiteGetTypeName,
735 "isToplevel", CallSiteIsToplevel,
736 "isEval", CallSiteIsEval,
737 "getEvalOrigin", CallSiteGetEvalOrigin,
738 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
739 "getFunction", CallSiteGetFunction,
740 "getFunctionName", CallSiteGetFunctionName,
741 "getMethodName", CallSiteGetMethodName,
742 "getFileName", CallSiteGetFileName,
743 "getLineNumber", CallSiteGetLineNumber,
744 "getColumnNumber", CallSiteGetColumnNumber,
745 "isNative", CallSiteIsNative,
746 "getPosition", CallSiteGetPosition,
747 "isConstructor", CallSiteIsConstructor,
748 "toString", CallSiteToString
752 function FormatEvalOrigin(script) {
753 var sourceURL = script.nameOrSourceURL();
758 var eval_origin = "eval at ";
759 if (script.eval_from_function_name) {
760 eval_origin += script.eval_from_function_name;
762 eval_origin += "<anonymous>";
765 var eval_from_script = script.eval_from_script;
766 if (eval_from_script) {
767 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
768 // eval script originated from another eval.
769 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
771 // eval script originated from "real" source.
772 if (eval_from_script.name) {
773 eval_origin += " (" + eval_from_script.name;
774 var location = eval_from_script.locationFromPosition(
775 script.eval_from_script_position, true);
777 eval_origin += ":" + (location.line + 1);
778 eval_origin += ":" + (location.column + 1);
782 eval_origin += " (unknown source)";
791 function FormatErrorString(error) {
793 return %_CallFunction(error, ErrorToString);
796 return "<error: " + e + ">";
804 function GetStackFrames(raw_stack) {
805 var frames = new InternalArray();
806 var sloppy_frames = raw_stack[0];
807 for (var i = 1; i < raw_stack.length; i += 4) {
808 var recv = raw_stack[i];
809 var fun = raw_stack[i + 1];
810 var code = raw_stack[i + 2];
811 var pc = raw_stack[i + 3];
812 var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
814 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
820 // Flag to prevent recursive call of Error.prepareStackTrace.
821 var formatting_custom_stack_trace = false;
824 function FormatStackTrace(obj, raw_stack) {
825 var frames = GetStackFrames(raw_stack);
826 if (IS_FUNCTION(GlobalError.prepareStackTrace) &&
827 !formatting_custom_stack_trace) {
829 %MoveArrayContents(frames, array);
830 formatting_custom_stack_trace = true;
831 var stack_trace = UNDEFINED;
833 stack_trace = GlobalError.prepareStackTrace(obj, array);
835 throw e; // The custom formatting function threw. Rethrow.
837 formatting_custom_stack_trace = false;
842 var lines = new InternalArray();
843 lines.push(FormatErrorString(obj));
844 for (var i = 0; i < frames.length; i++) {
845 var frame = frames[i];
848 line = frame.toString();
851 line = "<error: " + e + ">";
853 // Any code that reaches this point is seriously nasty!
857 lines.push(" at " + line);
859 return %_CallFunction(lines, "\n", ArrayJoin);
863 function GetTypeName(receiver, requireConstructor) {
864 if (IS_NULL_OR_UNDEFINED(receiver)) return null;
865 var constructor = receiver.constructor;
867 return requireConstructor ? null :
868 %_CallFunction(receiver, NoSideEffectsObjectToString);
870 var constructorName = constructor.name;
871 if (!constructorName) {
872 return requireConstructor ? null :
873 %_CallFunction(receiver, NoSideEffectsObjectToString);
875 return constructorName;
879 // Format the stack trace if not yet done, and return it.
880 // Cache the formatted stack trace on the holder.
881 var StackTraceGetter = function() {
882 var formatted_stack_trace = UNDEFINED;
885 var formatted_stack_trace =
886 GET_PRIVATE(holder, formattedStackTraceSymbol);
887 if (IS_UNDEFINED(formatted_stack_trace)) {
888 // No formatted stack trace available.
889 var stack_trace = GET_PRIVATE(holder, stackTraceSymbol);
890 if (IS_UNDEFINED(stack_trace)) {
891 // Neither formatted nor structured stack trace available.
892 // Look further up the prototype chain.
893 holder = %_GetPrototype(holder);
896 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
897 SET_PRIVATE(holder, stackTraceSymbol, UNDEFINED);
898 SET_PRIVATE(holder, formattedStackTraceSymbol, formatted_stack_trace);
900 return formatted_stack_trace;
906 // If the receiver equals the holder, set the formatted stack trace that the
908 var StackTraceSetter = function(v) {
909 if (HAS_PRIVATE(this, stackTraceSymbol)) {
910 SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
911 SET_PRIVATE(this, formattedStackTraceSymbol, v);
916 // Use a dummy function since we do not actually want to capture a stack trace
917 // when constructing the initial Error prototytpes.
918 var captureStackTrace = function() {};
921 // Define special error type constructors.
922 function DefineError(global, f) {
923 // Store the error function in both the global object
924 // and the runtime object. The function is fetched
925 // from the runtime object when throwing errors from
926 // within the runtime system to avoid strange side
927 // effects when overwriting the error functions from
930 %AddNamedProperty(global, name, f, DONT_ENUM);
931 // Configure the error function.
932 if (name == 'Error') {
933 // The prototype of the Error object must itself be an error.
934 // However, it can't be an instance of the Error object because
935 // it hasn't been properly configured yet. Instead we create a
936 // special not-a-true-error-but-close-enough object.
937 var ErrorPrototype = function() {};
938 %FunctionSetPrototype(ErrorPrototype, GlobalObject.prototype);
939 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
940 %FunctionSetPrototype(f, new ErrorPrototype());
942 %FunctionSetPrototype(f, new GlobalError());
943 %InternalSetPrototype(f, GlobalError);
945 %FunctionSetInstanceClassName(f, 'Error');
946 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
947 %AddNamedProperty(f.prototype, 'name', name, DONT_ENUM);
948 %SetCode(f, function(m) {
949 if (%_IsConstructCall()) {
950 try { captureStackTrace(this, f); } catch (e) { }
951 // Define all the expected properties directly on the error
952 // object. This avoids going through getters and setters defined
953 // on prototype objects.
954 if (!IS_UNDEFINED(m)) {
955 %AddNamedProperty(this, 'message', TO_STRING(m), DONT_ENUM);
965 GlobalError = DefineError(global, function Error() { });
966 GlobalEvalError = DefineError(global, function EvalError() { });
967 GlobalRangeError = DefineError(global, function RangeError() { });
968 GlobalReferenceError = DefineError(global, function ReferenceError() { });
969 GlobalSyntaxError = DefineError(global, function SyntaxError() { });
970 GlobalTypeError = DefineError(global, function TypeError() { });
971 GlobalURIError = DefineError(global, function URIError() { });
973 %AddNamedProperty(GlobalError.prototype, 'message', '', DONT_ENUM);
975 function ErrorToString() {
976 if (!IS_SPEC_OBJECT(this)) {
977 throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
980 return %ErrorToStringRT(this);
983 utils.InstallFunctions(GlobalError.prototype, DONT_ENUM,
984 ['toString', ErrorToString]);
986 $errorToString = ErrorToString;
988 MakeError = function(type, arg0, arg1, arg2) {
989 return MakeGenericError(GlobalError, type, arg0, arg1, arg2);
992 MakeRangeError = function(type, arg0, arg1, arg2) {
993 return MakeGenericError(GlobalRangeError, type, arg0, arg1, arg2);
996 MakeSyntaxError = function(type, arg0, arg1, arg2) {
997 return MakeGenericError(GlobalSyntaxError, type, arg0, arg1, arg2);
1000 MakeTypeError = function(type, arg0, arg1, arg2) {
1001 return MakeGenericError(GlobalTypeError, type, arg0, arg1, arg2);
1004 MakeURIError = function() {
1005 return MakeGenericError(GlobalURIError, kURIMalformed);
1008 // Boilerplate for exceptions for stack overflows. Used from
1009 // Isolate::StackOverflow().
1010 var StackOverflowBoilerplate = MakeRangeError(kStackOverflow);
1011 %DefineAccessorPropertyUnchecked(StackOverflowBoilerplate, 'stack',
1012 StackTraceGetter, StackTraceSetter,
1015 // Define actual captureStackTrace function after everything has been set up.
1016 captureStackTrace = function captureStackTrace(obj, cons_opt) {
1017 // Define accessors first, as this may fail and throw.
1018 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
1019 set: StackTraceSetter,
1020 configurable: true });
1021 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
1024 GlobalError.captureStackTrace = captureStackTrace;
1027 "error_function", GlobalError,
1028 "eval_error_function", GlobalEvalError,
1029 "get_stack_trace_line_fun", GetStackTraceLine,
1030 "make_error_function", MakeGenericError,
1031 "make_range_error", MakeRangeError,
1032 "make_type_error", MakeTypeError,
1033 "message_get_column_number", GetColumnNumber,
1034 "message_get_line_number", GetLineNumber,
1035 "message_get_source_line", GetSourceLine,
1036 "no_side_effect_to_string_fun", NoSideEffectToString,
1037 "range_error_function", GlobalRangeError,
1038 "reference_error_function", GlobalReferenceError,
1039 "stack_overflow_boilerplate", StackOverflowBoilerplate,
1040 "syntax_error_function", GlobalSyntaxError,
1041 "to_detail_string_fun", ToDetailString,
1042 "type_error_function", GlobalTypeError,
1043 "uri_error_function", GlobalURIError,