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");
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;
69 utils.ImportNow(function(from) {
70 ToString = from.ToString;
73 // -------------------------------------------------------------------
79 var GlobalSyntaxError;
80 var GlobalReferenceError;
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)) + "]";
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);
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);
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 + ">";
127 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
128 return %_CallFunction(obj, ErrorToString);
131 return %_CallFunction(obj, NoSideEffectsObjectToString);
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)) {
144 case 'ReferenceError':
151 var objToString = %GetDataProperty(obj, "toString");
152 return obj instanceof GlobalError && objToString === ErrorToString;
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);
164 return ToString(obj);
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 + ">";
179 return ToStringCheckErrorObject(obj);
183 function MakeGenericError(constructor, type, arg0, arg1, arg2) {
184 var error = new constructor(FormatMessage(type, arg0, arg1, arg2));
185 error[internalErrorSymbol] = true;
191 * Set up the Script function and constructor.
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);
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);
208 return %FormatMessageString(type, arg0, arg1, arg2);
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;
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;
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();
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.
252 function ScriptLineFromPosition(position) {
254 var upper = this.lineCount() - 1;
255 var line_ends = this.line_ends;
257 // We'll never find invalid positions so bail right away.
258 if (position > line_ends[upper]) {
262 // This means we don't have to safe-guard indexing line_ends[i - 1].
263 if (position <= line_ends[0]) {
267 // Binary search to find line # from position range.
269 var i = (lower + upper) >> 1;
271 if (position > line_ends[i]) {
273 } else if (position <= line_ends[i - 1]) {
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.
291 function ScriptLocationFromPosition(position,
292 include_resource_offset) {
293 var line = this.lineFromPosition(position);
294 if (line == -1) return null;
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') {
303 var column = position - start;
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;
313 return new SourceLocation(this, position, line, column, start, end);
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.
329 * @return {SourceLocation}
330 * If line is negative or not in the source null is returned.
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.
336 if (!IS_UNDEFINED(opt_line)) {
337 line = opt_line - this.line_offset;
340 // Default is first column. If on the first line add the offset within the
342 var column = opt_column || 0;
344 column -= this.column_offset;
347 var offset_position = opt_offset_position || 0;
348 if (line < 0 || column < 0 || offset_position < 0) return null;
350 return this.locationFromPosition(offset_position + column, false);
352 // Find the line where the offset position is located.
353 var offset_line = this.lineFromPosition(offset_position);
355 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
359 return this.locationFromPosition(
360 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
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.
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
375 function ScriptSourceSlice(opt_from_line, opt_to_line) {
376 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
378 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
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();
388 if (from_line >= this.lineCount() ||
390 from_line > to_line) {
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;
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);
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.
410 if (!IS_UNDEFINED(opt_line)) {
411 line = opt_line - this.line_offset;
415 if (line < 0 || this.lineCount() <= line) {
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);
428 * Returns the number of source lines.
430 * Number of source lines.
432 function ScriptLineCount() {
433 // Return number of source lines.
434 return this.line_ends.length;
439 * Returns the position of the nth line end.
441 * Zero-based position of the nth line end in the script.
443 function ScriptLineEnd(n) {
444 return this.line_ends[n];
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.
455 * @return {?string} script name if present, value for //# sourceURL or
456 * deprecated //@ sourceURL comment otherwise.
458 function ScriptNameOrSourceURL() {
459 if (this.source_url) return this.source_url;
464 utils.SetUpLockedPrototype(Script, [
468 "source_mapping_url",
473 "lineFromPosition", ScriptLineFromPosition,
474 "locationFromPosition", ScriptLocationFromPosition,
475 "locationFromLine", ScriptLocationFromLine,
476 "sourceSlice", ScriptSourceSlice,
477 "sourceLine", ScriptSourceLine,
478 "lineCount", ScriptLineCount,
479 "nameOrSourceURL", ScriptNameOrSourceURL,
480 "lineEnd", ScriptLineEnd
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
506 function SourceLocation(script, position, line, column, start, end) {
507 this.script = script;
508 this.position = position;
510 this.column = column;
517 * Get the source text for a SourceLocation
519 * Source text for this location.
521 function SourceLocationSourceText() {
522 return %_CallFunction(this.script.source,
529 utils.SetUpLockedPrototype(SourceLocation,
530 ["script", "position", "line", "column", "start", "end"],
531 ["sourceText", SourceLocationSourceText]
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
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;
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)
566 function SourceSliceSourceText() {
567 return %_CallFunction(this.script.source,
573 utils.SetUpLockedPrototype(SourceSlice,
574 ["script", "from_line", "to_line", "from_position", "to_position"],
575 ["sourceText", SourceSliceSourceText]
579 function GetStackTraceLine(recv, fun, pos, isGlobal) {
580 return new CallSite(recv, fun, pos, false).toString();
583 // ----------------------------------------------------------------------------
584 // Error implementation
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);
593 function CallSiteGetThis() {
594 return GET_PRIVATE(this, callSiteStrictSymbol)
595 ? UNDEFINED : GET_PRIVATE(this, callSiteReceiverSymbol);
598 function CallSiteGetFunction() {
599 return GET_PRIVATE(this, callSiteStrictSymbol)
600 ? UNDEFINED : GET_PRIVATE(this, callSiteFunctionSymbol);
603 function CallSiteGetPosition() {
604 return GET_PRIVATE(this, callSitePositionSymbol);
607 function CallSiteGetTypeName() {
608 return GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), false);
611 function CallSiteIsToplevel() {
612 return %CallSiteIsToplevelRT(this);
615 function CallSiteIsEval() {
616 return %CallSiteIsEvalRT(this);
619 function CallSiteGetEvalOrigin() {
620 var script = %FunctionGetScript(GET_PRIVATE(this, callSiteFunctionSymbol));
621 return FormatEvalOrigin(script);
624 function CallSiteGetScriptNameOrSourceURL() {
625 return %CallSiteGetScriptNameOrSourceUrlRT(this);
628 function CallSiteGetFunctionName() {
629 // See if the function knows its own name
630 return %CallSiteGetFunctionNameRT(this);
633 function CallSiteGetMethodName() {
634 // See if we can find a unique property on the receiver that holds
636 return %CallSiteGetMethodNameRT(this);
639 function CallSiteGetFileName() {
640 return %CallSiteGetFileNameRT(this);
643 function CallSiteGetLineNumber() {
644 return %CallSiteGetLineNumberRT(this);
647 function CallSiteGetColumnNumber() {
648 return %CallSiteGetColumnNumberRT(this);
651 function CallSiteIsNative() {
652 return %CallSiteIsNativeRT(this);
655 function CallSiteIsConstructor() {
656 return %CallSiteIsConstructorRT(this);
659 function CallSiteToString() {
661 var fileLocation = "";
662 if (this.isNative()) {
663 fileLocation = "native";
665 fileName = this.getScriptNameOrSourceURL();
666 if (!fileName && this.isEval()) {
667 fileLocation = this.getEvalOrigin();
668 fileLocation += ", "; // Expecting source position to follow.
672 fileLocation += fileName;
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
677 fileLocation += "<anonymous>";
679 var lineNumber = this.getLineNumber();
680 if (lineNumber != null) {
681 fileLocation += ":" + lineNumber;
682 var columnNumber = this.getColumnNumber();
684 fileLocation += ":" + columnNumber;
690 var functionName = this.getFunctionName();
691 var addSuffix = true;
692 var isConstructor = this.isConstructor();
693 var isMethodCall = !(this.isToplevel() || isConstructor);
695 var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
696 var methodName = this.getMethodName();
699 %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
700 line += typeName + ".";
702 line += functionName;
704 (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
705 functionName.length - methodName.length - 1)) {
706 line += " [as " + methodName + "]";
709 line += typeName + "." + (methodName || "<anonymous>");
711 } else if (isConstructor) {
712 line += "new " + (functionName || "<anonymous>");
713 } else if (functionName) {
714 line += functionName;
716 line += fileLocation;
720 line += " (" + fileLocation + ")";
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
745 function FormatEvalOrigin(script) {
746 var sourceURL = script.nameOrSourceURL();
751 var eval_origin = "eval at ";
752 if (script.eval_from_function_name) {
753 eval_origin += script.eval_from_function_name;
755 eval_origin += "<anonymous>";
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) + ")";
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);
770 eval_origin += ":" + (location.line + 1);
771 eval_origin += ":" + (location.column + 1);
775 eval_origin += " (unknown source)";
784 function FormatErrorString(error) {
786 return %_CallFunction(error, ErrorToString);
789 return "<error: " + e + ">";
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);
807 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
813 // Flag to prevent recursive call of Error.prepareStackTrace.
814 var formatting_custom_stack_trace = false;
817 function FormatStackTrace(obj, raw_stack) {
818 var frames = GetStackFrames(raw_stack);
819 if (IS_FUNCTION(GlobalError.prepareStackTrace) &&
820 !formatting_custom_stack_trace) {
822 %MoveArrayContents(frames, array);
823 formatting_custom_stack_trace = true;
824 var stack_trace = UNDEFINED;
826 stack_trace = GlobalError.prepareStackTrace(obj, array);
828 throw e; // The custom formatting function threw. Rethrow.
830 formatting_custom_stack_trace = false;
835 var lines = new InternalArray();
836 lines.push(FormatErrorString(obj));
837 for (var i = 0; i < frames.length; i++) {
838 var frame = frames[i];
841 line = frame.toString();
844 line = "<error: " + e + ">";
846 // Any code that reaches this point is seriously nasty!
850 lines.push(" at " + line);
852 return %_CallFunction(lines, "\n", ArrayJoin);
856 function GetTypeName(receiver, requireConstructor) {
857 if (IS_NULL_OR_UNDEFINED(receiver)) return null;
858 var constructor = receiver.constructor;
860 return requireConstructor ? null :
861 %_CallFunction(receiver, NoSideEffectsObjectToString);
863 var constructorName = constructor.name;
864 if (!constructorName) {
865 return requireConstructor ? null :
866 %_CallFunction(receiver, NoSideEffectsObjectToString);
868 return constructorName;
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;
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);
889 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
890 SET_PRIVATE(holder, stackTraceSymbol, UNDEFINED);
891 SET_PRIVATE(holder, formattedStackTraceSymbol, formatted_stack_trace);
893 return formatted_stack_trace;
899 // If the receiver equals the holder, set the formatted stack trace that the
901 var StackTraceSetter = function(v) {
902 if (HAS_PRIVATE(this, stackTraceSymbol)) {
903 SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
904 SET_PRIVATE(this, formattedStackTraceSymbol, v);
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() {};
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
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());
935 %FunctionSetPrototype(f, new GlobalError());
936 %InternalSetPrototype(f, GlobalError);
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);
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() { });
966 %AddNamedProperty(GlobalError.prototype, 'message', '', DONT_ENUM);
968 function ErrorToString() {
969 if (!IS_SPEC_OBJECT(this)) {
970 throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
973 return %ErrorToStringRT(this);
976 utils.InstallFunctions(GlobalError.prototype, DONT_ENUM,
977 ['toString', ErrorToString]);
979 $errorToString = ErrorToString;
981 MakeError = function(type, arg0, arg1, arg2) {
982 return MakeGenericError(GlobalError, type, arg0, arg1, arg2);
985 MakeRangeError = function(type, arg0, arg1, arg2) {
986 return MakeGenericError(GlobalRangeError, type, arg0, arg1, arg2);
989 MakeSyntaxError = function(type, arg0, arg1, arg2) {
990 return MakeGenericError(GlobalSyntaxError, type, arg0, arg1, arg2);
993 MakeTypeError = function(type, arg0, arg1, arg2) {
994 return MakeGenericError(GlobalTypeError, type, arg0, arg1, arg2);
997 MakeURIError = function() {
998 return MakeGenericError(GlobalURIError, kURIMalformed);
1001 // Boilerplate for exceptions for stack overflows. Used from
1002 // Isolate::StackOverflow().
1003 var StackOverflowBoilerplate = MakeRangeError(kStackOverflow);
1004 %DefineAccessorPropertyUnchecked(StackOverflowBoilerplate, 'stack',
1005 StackTraceGetter, StackTraceSetter,
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);
1017 GlobalError.captureStackTrace = captureStackTrace;
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;