| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 | 77 |
| 78 var kMessages = 0; | 78 var kMessages = 0; |
| 79 | 79 |
| 80 | 80 |
| 81 function FormatString(format, args) { | 81 function FormatString(format, args) { |
| 82 var result = format; | 82 var result = format; |
| 83 for (var i = 0; i < args.length; i++) { | 83 for (var i = 0; i < args.length; i++) { |
| 84 var str; | 84 var str; |
| 85 try { str = ToDetailString(args[i]); } | 85 try { |
| 86 catch (e) { str = "#<error>"; } | 86 str = ToDetailString(args[i]); |
| 87 } catch (e) { |
| 88 str = "#<error>"; |
| 89 } |
| 87 result = ArrayJoin.call(StringSplit.call(result, "%" + i), str); | 90 result = ArrayJoin.call(StringSplit.call(result, "%" + i), str); |
| 88 } | 91 } |
| 89 return result; | 92 return result; |
| 90 } | 93 } |
| 91 | 94 |
| 92 | 95 |
| 93 function ToDetailString(obj) { | 96 // To check if something is a native error we need to check the |
| 94 if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toStri
ng) { | 97 // concrete native error types. It is not enough to check "obj |
| 95 var constructor = obj.constructor; | 98 // instanceof $Error" because user code can replace |
| 96 if (!constructor) return ToString(obj); | 99 // NativeError.prototype.__proto__. User code cannot replace |
| 97 var constructorName = constructor.name; | 100 // NativeError.prototype though and therefore this is a safe test. |
| 98 if (!constructorName) return ToString(obj); | 101 function IsNativeErrorObject(obj) { |
| 99 return "#<" + GetInstanceName(constructorName) + ">"; | 102 return (obj instanceof $Error) || |
| 103 (obj instanceof $EvalError) || |
| 104 (obj instanceof $RangeError) || |
| 105 (obj instanceof $ReferenceError) || |
| 106 (obj instanceof $SyntaxError) || |
| 107 (obj instanceof $TypeError) || |
| 108 (obj instanceof $URIError); |
| 109 } |
| 110 |
| 111 |
| 112 // When formatting internally created error messages, do not |
| 113 // invoke overwritten error toString methods but explicitly use |
| 114 // the error to string method. This is to avoid leaking error |
| 115 // objects between script tags in a browser setting. |
| 116 function ToStringCheckErrorObject(obj) { |
| 117 if (IsNativeErrorObject(obj)) { |
| 118 return %_CallFunction(obj, errorToString); |
| 100 } else { | 119 } else { |
| 101 return ToString(obj); | 120 return ToString(obj); |
| 102 } | 121 } |
| 103 } | 122 } |
| 104 | 123 |
| 124 |
| 125 function ToDetailString(obj) { |
| 126 if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toStri
ng) { |
| 127 var constructor = obj.constructor; |
| 128 if (!constructor) return ToStringCheckErrorObject(obj); |
| 129 var constructorName = constructor.name; |
| 130 if (!constructorName || !IS_STRING(constructorName)) { |
| 131 return ToStringCheckErrorObject(obj); |
| 132 } |
| 133 return "#<" + GetInstanceName(constructorName) + ">"; |
| 134 } else { |
| 135 return ToStringCheckErrorObject(obj); |
| 136 } |
| 137 } |
| 138 |
| 105 | 139 |
| 106 function MakeGenericError(constructor, type, args) { | 140 function MakeGenericError(constructor, type, args) { |
| 107 if (IS_UNDEFINED(args)) { | 141 if (IS_UNDEFINED(args)) { |
| 108 args = []; | 142 args = []; |
| 109 } | 143 } |
| 110 var e = new constructor(kAddMessageAccessorsMarker); | 144 var e = new constructor(kAddMessageAccessorsMarker); |
| 111 e.type = type; | 145 e.type = type; |
| 112 e.arguments = args; | 146 e.arguments = args; |
| 113 return e; | 147 return e; |
| 114 } | 148 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 illegal_continue: "Illegal continue statement", | 223 illegal_continue: "Illegal continue statement", |
| 190 illegal_return: "Illegal return statement", | 224 illegal_return: "Illegal return statement", |
| 191 error_loading_debugger: "Error loading debugger", | 225 error_loading_debugger: "Error loading debugger", |
| 192 no_input_to_regexp: "No input to %0", | 226 no_input_to_regexp: "No input to %0", |
| 193 invalid_json: "String '%0' is not valid JSON", | 227 invalid_json: "String '%0' is not valid JSON", |
| 194 circular_structure: "Converting circular structure to JSON", | 228 circular_structure: "Converting circular structure to JSON", |
| 195 obj_ctor_property_non_object: "Object.%0 called on non-object", | 229 obj_ctor_property_non_object: "Object.%0 called on non-object", |
| 196 array_indexof_not_defined: "Array.getIndexOf: Argument undefined", | 230 array_indexof_not_defined: "Array.getIndexOf: Argument undefined", |
| 197 object_not_extensible: "Can't add property %0, object is not extens
ible", | 231 object_not_extensible: "Can't add property %0, object is not extens
ible", |
| 198 illegal_access: "Illegal access", | 232 illegal_access: "Illegal access", |
| 199 invalid_preparser_data: "Invalid preparser data for function %0" | 233 invalid_preparser_data: "Invalid preparser data for function %0", |
| 234 strict_mode_with: "Strict mode code may not include a with sta
tement", |
| 235 strict_catch_variable: "Catch variable may not be eval or arguments
in strict mode", |
| 236 strict_param_name: "Parameter name eval or arguments is not all
owed in strict mode", |
| 237 strict_param_dupe: "Strict mode function may not have duplicate
parameter names", |
| 238 strict_var_name: "Variable name may not be eval or arguments
in strict mode", |
| 239 strict_function_name: "Function name may not be eval or arguments
in strict mode", |
| 240 strict_octal_literal: "Octal literals are not allowed in strict mo
de.", |
| 241 strict_duplicate_property: "Duplicate data property in object literal n
ot allowed in strict mode", |
| 242 accessor_data_property: "Object literal may not have data and access
or property with the same name", |
| 243 accessor_get_set: "Object literal may not have multiple get/se
t accessors with the same name", |
| 200 }; | 244 }; |
| 201 } | 245 } |
| 202 var format = kMessages[message.type]; | 246 var format = kMessages[message.type]; |
| 203 if (!format) return "<unknown message " + message.type + ">"; | 247 if (!format) return "<unknown message " + message.type + ">"; |
| 204 return FormatString(format, message.args); | 248 return FormatString(format, message.args); |
| 205 } | 249 } |
| 206 | 250 |
| 207 | 251 |
| 208 function GetLineNumber(message) { | 252 function GetLineNumber(message) { |
| 209 if (message.startPos == -1) return kNoLineNumberInfo; | 253 if (message.startPos == -1) return kNoLineNumberInfo; |
| (...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 // special not-a-true-error-but-close-enough object. | 980 // special not-a-true-error-but-close-enough object. |
| 937 function ErrorPrototype() {} | 981 function ErrorPrototype() {} |
| 938 %FunctionSetPrototype(ErrorPrototype, $Object.prototype); | 982 %FunctionSetPrototype(ErrorPrototype, $Object.prototype); |
| 939 %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); | 983 %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); |
| 940 %FunctionSetPrototype(f, new ErrorPrototype()); | 984 %FunctionSetPrototype(f, new ErrorPrototype()); |
| 941 } else { | 985 } else { |
| 942 %FunctionSetPrototype(f, new $Error()); | 986 %FunctionSetPrototype(f, new $Error()); |
| 943 } | 987 } |
| 944 %FunctionSetInstanceClassName(f, 'Error'); | 988 %FunctionSetInstanceClassName(f, 'Error'); |
| 945 %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); | 989 %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); |
| 946 f.prototype.name = name; | 990 // The name property on the prototype of error objects is not |
| 991 // specified as being read-one and dont-delete. However, allowing |
| 992 // overwriting allows leaks of error objects between script blocks |
| 993 // in the same context in a browser setting. Therefore we fix the |
| 994 // name. |
| 995 %SetProperty(f.prototype, "name", name, READ_ONLY | DONT_DELETE); |
| 947 %SetCode(f, function(m) { | 996 %SetCode(f, function(m) { |
| 948 if (%_IsConstructCall()) { | 997 if (%_IsConstructCall()) { |
| 949 // Define all the expected properties directly on the error | 998 // Define all the expected properties directly on the error |
| 950 // object. This avoids going through getters and setters defined | 999 // object. This avoids going through getters and setters defined |
| 951 // on prototype objects. | 1000 // on prototype objects. |
| 952 %IgnoreAttributesAndSetProperty(this, 'stack', void 0); | 1001 %IgnoreAttributesAndSetProperty(this, 'stack', void 0); |
| 953 %IgnoreAttributesAndSetProperty(this, 'arguments', void 0); | 1002 %IgnoreAttributesAndSetProperty(this, 'arguments', void 0); |
| 954 %IgnoreAttributesAndSetProperty(this, 'type', void 0); | 1003 %IgnoreAttributesAndSetProperty(this, 'type', void 0); |
| 955 if (m === kAddMessageAccessorsMarker) { | 1004 if (m === kAddMessageAccessorsMarker) { |
| 956 // DefineOneShotAccessor always inserts a message property and | 1005 // DefineOneShotAccessor always inserts a message property and |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 DefineError(function SyntaxError() { }); | 1037 DefineError(function SyntaxError() { }); |
| 989 DefineError(function ReferenceError() { }); | 1038 DefineError(function ReferenceError() { }); |
| 990 DefineError(function EvalError() { }); | 1039 DefineError(function EvalError() { }); |
| 991 DefineError(function URIError() { }); | 1040 DefineError(function URIError() { }); |
| 992 | 1041 |
| 993 $Error.captureStackTrace = captureStackTrace; | 1042 $Error.captureStackTrace = captureStackTrace; |
| 994 | 1043 |
| 995 // Setup extra properties of the Error.prototype object. | 1044 // Setup extra properties of the Error.prototype object. |
| 996 $Error.prototype.message = ''; | 1045 $Error.prototype.message = ''; |
| 997 | 1046 |
| 998 %SetProperty($Error.prototype, 'toString', function toString() { | 1047 // Global list of error objects visited during errorToString. This is |
| 999 var type = this.type; | 1048 // used to detect cycles in error toString formatting. |
| 1000 if (type && !this.hasOwnProperty("message")) { | 1049 var visited_errors = new $Array(); |
| 1001 return this.name + ": " + FormatMessage({ type: type, args: this.arguments }
); | 1050 var cyclic_error_marker = new $Object(); |
| 1051 |
| 1052 function errorToStringDetectCycle() { |
| 1053 if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker; |
| 1054 try { |
| 1055 var type = this.type; |
| 1056 if (type && !this.hasOwnProperty("message")) { |
| 1057 var formatted = FormatMessage({ type: type, args: this.arguments }); |
| 1058 return this.name + ": " + formatted; |
| 1059 } |
| 1060 var message = this.hasOwnProperty("message") ? (": " + this.message) : ""; |
| 1061 return this.name + message; |
| 1062 } finally { |
| 1063 visited_errors.pop(); |
| 1002 } | 1064 } |
| 1003 var message = this.hasOwnProperty("message") ? (": " + this.message) : ""; | 1065 } |
| 1004 return this.name + message; | |
| 1005 }, DONT_ENUM); | |
| 1006 | 1066 |
| 1067 function errorToString() { |
| 1068 // This helper function is needed because access to properties on |
| 1069 // the builtins object do not work inside of a catch clause. |
| 1070 function isCyclicErrorMarker(o) { return o === cyclic_error_marker; } |
| 1071 |
| 1072 try { |
| 1073 return %_CallFunction(this, errorToStringDetectCycle); |
| 1074 } catch(e) { |
| 1075 // If this error message was encountered already return the empty |
| 1076 // string for it instead of recursively formatting it. |
| 1077 if (isCyclicErrorMarker(e)) return ''; |
| 1078 else throw e; |
| 1079 } |
| 1080 } |
| 1081 |
| 1082 %FunctionSetName(errorToString, 'toString'); |
| 1083 %SetProperty($Error.prototype, 'toString', errorToString, DONT_ENUM); |
| 1007 | 1084 |
| 1008 // Boilerplate for exceptions for stack overflows. Used from | 1085 // Boilerplate for exceptions for stack overflows. Used from |
| 1009 // Isolate::StackOverflow(). | 1086 // Isolate::StackOverflow(). |
| 1010 const kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []); | 1087 const kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []); |
| OLD | NEW |