blob: a3adcf8634d05440dec2b03ad8ed373992653993 [file] [log] [blame]
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000028// -------------------------------------------------------------------
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000029//
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000030// If this object gets passed to an error constructor the error will
31// get an accessor for .message that constructs a descriptive error
32// message on access.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000033var kAddMessageAccessorsMarker = { };
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000034
fschneider@chromium.org1805e212011-09-05 10:49:12 +000035// This will be lazily initialized when first needed (and forcibly
36// overwritten even though it's const).
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000037var kMessages = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000039function FormatString(format, message) {
40 var args = %MessageGetArguments(message);
41 var result = "";
42 var arg_num = 0;
43 for (var i = 0; i < format.length; i++) {
44 var str = format[i];
fschneider@chromium.org1805e212011-09-05 10:49:12 +000045 if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) {
46 // Two-char string starts with "%".
47 var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0;
48 if (arg_num < 4) {
49 // str is one of %0, %1, %2 or %3.
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000050 try {
51 str = ToDetailString(args[arg_num]);
52 } catch (e) {
53 str = "#<error>";
54 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000055 }
ager@chromium.org378b34e2011-01-28 08:04:38 +000056 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000057 result += str;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000058 }
59 return result;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000060}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000061
62
ager@chromium.org0ee099b2011-01-25 14:06:47 +000063// To check if something is a native error we need to check the
64// concrete native error types. It is not enough to check "obj
65// instanceof $Error" because user code can replace
66// NativeError.prototype.__proto__. User code cannot replace
67// NativeError.prototype though and therefore this is a safe test.
68function IsNativeErrorObject(obj) {
69 return (obj instanceof $Error) ||
70 (obj instanceof $EvalError) ||
71 (obj instanceof $RangeError) ||
72 (obj instanceof $ReferenceError) ||
73 (obj instanceof $SyntaxError) ||
74 (obj instanceof $TypeError) ||
75 (obj instanceof $URIError);
76}
77
78
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000079// When formatting internally created error messages, do not
80// invoke overwritten error toString methods but explicitly use
81// the error to string method. This is to avoid leaking error
82// objects between script tags in a browser setting.
83function ToStringCheckErrorObject(obj) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +000084 if (IsNativeErrorObject(obj)) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000085 return %_CallFunction(obj, ErrorToString);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086 } else {
87 return ToString(obj);
88 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000089}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090
91
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000092function ToDetailString(obj) {
fschneider@chromium.org1805e212011-09-05 10:49:12 +000093 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000094 var constructor = obj.constructor;
fschneider@chromium.org1805e212011-09-05 10:49:12 +000095 if (typeof constructor == "function") {
96 var constructorName = constructor.name;
97 if (IS_STRING(constructorName) && constructorName !== "") {
98 return "#<" + constructorName + ">";
99 }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000100 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000101 }
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000102 return ToStringCheckErrorObject(obj);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000103}
104
105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106function MakeGenericError(constructor, type, args) {
ager@chromium.org3e875802009-06-29 08:26:34 +0000107 if (IS_UNDEFINED(args)) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000108 args = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000110 var e = new constructor(kAddMessageAccessorsMarker);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111 e.type = type;
112 e.arguments = args;
113 return e;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000114}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115
116
117/**
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000118 * Set up the Script function and constructor.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 */
120%FunctionSetInstanceClassName(Script, 'Script');
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000121%SetProperty(Script.prototype, 'constructor', Script,
122 DONT_ENUM | DONT_DELETE | READ_ONLY);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123%SetCode(Script, function(x) {
124 // Script objects can only be created by the VM.
125 throw new $Error("Not supported");
126});
127
128
129// Helper functions; called from the runtime system.
130function FormatMessage(message) {
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000131 if (kMessages === 0) {
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000132 var messagesDictionary = [
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000133 // Error
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000134 "cyclic_proto", ["Cyclic __proto__ value"],
135 "code_gen_from_strings", ["Code generation from strings disallowed for this context"],
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000136 // TypeError
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000137 "unexpected_token", ["Unexpected token ", "%0"],
138 "unexpected_token_number", ["Unexpected number"],
139 "unexpected_token_string", ["Unexpected string"],
140 "unexpected_token_identifier", ["Unexpected identifier"],
141 "unexpected_reserved", ["Unexpected reserved word"],
142 "unexpected_strict_reserved", ["Unexpected strict mode reserved word"],
143 "unexpected_eos", ["Unexpected end of input"],
144 "malformed_regexp", ["Invalid regular expression: /", "%0", "/: ", "%1"],
145 "unterminated_regexp", ["Invalid regular expression: missing /"],
146 "regexp_flags", ["Cannot supply flags when constructing one RegExp from another"],
147 "incompatible_method_receiver", ["Method ", "%0", " called on incompatible receiver ", "%1"],
148 "invalid_lhs_in_assignment", ["Invalid left-hand side in assignment"],
149 "invalid_lhs_in_for_in", ["Invalid left-hand side in for-in"],
150 "invalid_lhs_in_postfix_op", ["Invalid left-hand side expression in postfix operation"],
151 "invalid_lhs_in_prefix_op", ["Invalid left-hand side expression in prefix operation"],
152 "multiple_defaults_in_switch", ["More than one default clause in switch statement"],
153 "newline_after_throw", ["Illegal newline after throw"],
154 "redeclaration", ["%0", " '", "%1", "' has already been declared"],
155 "no_catch_or_finally", ["Missing catch or finally after try"],
156 "unknown_label", ["Undefined label '", "%0", "'"],
157 "uncaught_exception", ["Uncaught ", "%0"],
158 "stack_trace", ["Stack Trace:\n", "%0"],
159 "called_non_callable", ["%0", " is not a function"],
160 "undefined_method", ["Object ", "%1", " has no method '", "%0", "'"],
161 "property_not_function", ["Property '", "%0", "' of object ", "%1", " is not a function"],
162 "cannot_convert_to_primitive", ["Cannot convert object to primitive value"],
163 "not_constructor", ["%0", " is not a constructor"],
164 "not_defined", ["%0", " is not defined"],
165 "non_object_property_load", ["Cannot read property '", "%0", "' of ", "%1"],
166 "non_object_property_store", ["Cannot set property '", "%0", "' of ", "%1"],
167 "non_object_property_call", ["Cannot call method '", "%0", "' of ", "%1"],
168 "with_expression", ["%0", " has no properties"],
169 "illegal_invocation", ["Illegal invocation"],
170 "no_setter_in_callback", ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
171 "apply_non_function", ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
172 "apply_wrong_args", ["Function.prototype.apply: Arguments list has wrong type"],
173 "invalid_in_operator_use", ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
174 "instanceof_function_expected", ["Expecting a function in instanceof check, but got ", "%0"],
175 "instanceof_nonobject_proto", ["Function has non-object prototype '", "%0", "' in instanceof check"],
176 "null_to_object", ["Cannot convert null to object"],
177 "reduce_no_initial", ["Reduce of empty array with no initial value"],
178 "getter_must_be_callable", ["Getter must be a function: ", "%0"],
179 "setter_must_be_callable", ["Setter must be a function: ", "%0"],
180 "value_and_accessor", ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"],
181 "proto_object_or_null", ["Object prototype may only be an Object or null"],
182 "property_desc_object", ["Property description must be an object: ", "%0"],
183 "redefine_disallowed", ["Cannot redefine property: ", "%0"],
184 "define_disallowed", ["Cannot define property:", "%0", ", object is not extensible."],
185 "non_extensible_proto", ["%0", " is not extensible"],
186 "handler_non_object", ["Proxy.", "%0", " called with non-object as handler"],
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000187 "proto_non_object", ["Proxy.", "%0", " called with non-object as prototype"],
188 "trap_function_expected", ["Proxy.", "%0", " called with non-function for '", "%1", "' trap"],
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000189 "handler_trap_missing", ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
190 "handler_trap_must_be_callable", ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000191 "handler_returned_false", ["Proxy handler ", "%0", " returned false from '", "%1", "' trap"],
192 "handler_returned_undefined", ["Proxy handler ", "%0", " returned undefined from '", "%1", "' trap"],
193 "proxy_prop_not_configurable", ["Proxy handler ", "%0", " returned non-configurable descriptor for property '", "%2", "' from '", "%1", "' trap"],
194 "proxy_non_object_prop_names", ["Trap '", "%1", "' returned non-object ", "%0"],
195 "proxy_repeated_prop_name", ["Trap '", "%1", "' returned repeated property name '", "%2", "'"],
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000196 "invalid_weakmap_key", ["Invalid value used as weak map key"],
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000197 // RangeError
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000198 "invalid_array_length", ["Invalid array length"],
199 "stack_overflow", ["Maximum call stack size exceeded"],
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000200 "invalid_time_value", ["Invalid time value"],
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000201 // SyntaxError
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000202 "unable_to_parse", ["Parse error"],
203 "invalid_regexp_flags", ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
204 "invalid_regexp", ["Invalid RegExp pattern /", "%0", "/"],
205 "illegal_break", ["Illegal break statement"],
206 "illegal_continue", ["Illegal continue statement"],
207 "illegal_return", ["Illegal return statement"],
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000208 "illegal_let", ["Illegal let declaration outside extended mode"],
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000209 "error_loading_debugger", ["Error loading debugger"],
210 "no_input_to_regexp", ["No input to ", "%0"],
211 "invalid_json", ["String '", "%0", "' is not valid JSON"],
212 "circular_structure", ["Converting circular structure to JSON"],
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000213 "called_on_non_object", ["%0", " called on non-object"],
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000214 "called_on_null_or_undefined", ["%0", " called on null or undefined"],
215 "array_indexof_not_defined", ["Array.getIndexOf: Argument undefined"],
216 "object_not_extensible", ["Can't add property ", "%0", ", object is not extensible"],
217 "illegal_access", ["Illegal access"],
218 "invalid_preparser_data", ["Invalid preparser data for function ", "%0"],
219 "strict_mode_with", ["Strict mode code may not include a with statement"],
220 "strict_catch_variable", ["Catch variable may not be eval or arguments in strict mode"],
221 "too_many_arguments", ["Too many arguments in function call (only 32766 allowed)"],
222 "too_many_parameters", ["Too many parameters in function definition (only 32766 allowed)"],
223 "too_many_variables", ["Too many variables declared (only 32767 allowed)"],
224 "strict_param_name", ["Parameter name eval or arguments is not allowed in strict mode"],
225 "strict_param_dupe", ["Strict mode function may not have duplicate parameter names"],
226 "strict_var_name", ["Variable name may not be eval or arguments in strict mode"],
227 "strict_function_name", ["Function name may not be eval or arguments in strict mode"],
228 "strict_octal_literal", ["Octal literals are not allowed in strict mode."],
229 "strict_duplicate_property", ["Duplicate data property in object literal not allowed in strict mode"],
230 "accessor_data_property", ["Object literal may not have data and accessor property with the same name"],
231 "accessor_get_set", ["Object literal may not have multiple get/set accessors with the same name"],
232 "strict_lhs_assignment", ["Assignment to eval or arguments is not allowed in strict mode"],
233 "strict_lhs_postfix", ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
234 "strict_lhs_prefix", ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
235 "strict_reserved_word", ["Use of future reserved word in strict mode"],
236 "strict_delete", ["Delete of an unqualified identifier in strict mode."],
237 "strict_delete_property", ["Cannot delete property '", "%0", "' of ", "%1"],
238 "strict_const", ["Use of const in strict mode."],
239 "strict_function", ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
240 "strict_read_only_property", ["Cannot assign to read only property '", "%0", "' of ", "%1"],
241 "strict_cannot_assign", ["Cannot assign to read only '", "%0", "' in strict mode"],
242 "strict_poison_pill", ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"],
243 "strict_caller", ["Illegal access to a strict mode caller function."],
244 "unprotected_let", ["Illegal let declaration in unprotected statement context."],
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000245 "unprotected_const", ["Illegal const declaration in unprotected statement context."],
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000246 "cant_prevent_ext_external_array_elements", ["Cannot prevent extension of an object with external array elements"],
247 "redef_external_array_element", ["Cannot redefine a property of an object with external array elements"],
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000248 "harmony_const_assign", ["Assignment to constant variable."],
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000249 "invalid_module_path", ["Module does not export '", "%0", "', or export is not itself a module"],
250 "module_type_error", ["Module '", "%0", "' used improperly"],
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000251 ];
252 var messages = { __proto__ : null };
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000253 for (var i = 0; i < messagesDictionary.length; i += 2) {
254 var key = messagesDictionary[i];
255 var format = messagesDictionary[i + 1];
ricow@chromium.org93720df2011-11-07 11:02:21 +0000256
257 for (var j = 0; j < format.length; j++) {
258 %IgnoreAttributesAndSetProperty(format, %_NumberToString(j), format[j],
259 DONT_DELETE | READ_ONLY | DONT_ENUM);
260 }
261 %IgnoreAttributesAndSetProperty(format, 'length', format.length,
262 DONT_DELETE | READ_ONLY | DONT_ENUM);
263 %PreventExtensions(format);
264 %IgnoreAttributesAndSetProperty(messages,
265 key,
266 format,
267 DONT_DELETE | DONT_ENUM | READ_ONLY);
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000268 }
269 %PreventExtensions(messages);
270 %IgnoreAttributesAndSetProperty(builtins, "kMessages",
271 messages,
272 DONT_DELETE | DONT_ENUM | READ_ONLY);
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000273 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000274 var message_type = %MessageGetType(message);
275 var format = kMessages[message_type];
276 if (!format) return "<unknown message " + message_type + ">";
277 return FormatString(format, message);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000278}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279
280
281function GetLineNumber(message) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000282 var start_position = %MessageGetStartPosition(message);
283 if (start_position == -1) return kNoLineNumberInfo;
284 var script = %MessageGetScript(message);
285 var location = script.locationFromPosition(start_position, true);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000286 if (location == null) return kNoLineNumberInfo;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000287 return location.line + 1;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000288}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289
290
291// Returns the source code line containing the given source
292// position, or the empty string if the position is invalid.
293function GetSourceLine(message) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000294 var script = %MessageGetScript(message);
295 var start_position = %MessageGetStartPosition(message);
296 var location = script.locationFromPosition(start_position, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 if (location == null) return "";
298 location.restrict();
299 return location.sourceText();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000300}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301
302
303function MakeTypeError(type, args) {
304 return MakeGenericError($TypeError, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000305}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306
307
308function MakeRangeError(type, args) {
309 return MakeGenericError($RangeError, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000310}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311
312
313function MakeSyntaxError(type, args) {
314 return MakeGenericError($SyntaxError, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000315}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316
317
318function MakeReferenceError(type, args) {
319 return MakeGenericError($ReferenceError, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000320}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321
322
323function MakeEvalError(type, args) {
324 return MakeGenericError($EvalError, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000325}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000326
327
328function MakeError(type, args) {
329 return MakeGenericError($Error, type, args);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000330}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000332/**
333 * Find a line number given a specific source position.
334 * @param {number} position The source position.
335 * @return {number} 0 if input too small, -1 if input too large,
336 else the line number.
337 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000338function ScriptLineFromPosition(position) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000339 var lower = 0;
340 var upper = this.lineCount() - 1;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000341 var line_ends = this.line_ends;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000342
343 // We'll never find invalid positions so bail right away.
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000344 if (position > line_ends[upper]) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000345 return -1;
346 }
347
348 // This means we don't have to safe-guard indexing line_ends[i - 1].
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000349 if (position <= line_ends[0]) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000350 return 0;
351 }
352
353 // Binary search to find line # from position range.
354 while (upper >= 1) {
355 var i = (lower + upper) >> 1;
356
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000357 if (position > line_ends[i]) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000358 lower = i + 1;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000359 } else if (position <= line_ends[i - 1]) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000360 upper = i - 1;
361 } else {
362 return i;
363 }
364 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000365
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000366 return -1;
367}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368
369/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370 * Get information on a specific source position.
371 * @param {number} position The source position
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000372 * @param {boolean} include_resource_offset Set to true to have the resource
373 * offset added to the location
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000374 * @return {SourceLocation}
375 * If line is negative or not in the source null is returned.
376 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000377function ScriptLocationFromPosition(position,
378 include_resource_offset) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000379 var line = this.lineFromPosition(position);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 if (line == -1) return null;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382 // Determine start, end and column.
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000383 var line_ends = this.line_ends;
384 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
385 var end = line_ends[line];
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000386 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
387 end--;
388 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389 var column = position - start;
390
391 // Adjust according to the offset within the resource.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000392 if (include_resource_offset) {
393 line += this.line_offset;
394 if (line == this.line_offset) {
395 column += this.column_offset;
396 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397 }
398
399 return new SourceLocation(this, position, line, column, start, end);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000400}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401
402
403/**
404 * Get information on a specific source line and column possibly offset by a
405 * fixed source position. This function is used to find a source position from
406 * a line and column position. The fixed source position offset is typically
407 * used to find a source position in a function based on a line and column in
408 * the source for the function alone. The offset passed will then be the
409 * start position of the source for the function within the full script source.
410 * @param {number} opt_line The line within the source. Default value is 0
411 * @param {number} opt_column The column in within the line. Default value is 0
412 * @param {number} opt_offset_position The offset from the begining of the
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000413 * source from where the line and column calculation starts.
414 * Default value is 0
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415 * @return {SourceLocation}
416 * If line is negative or not in the source null is returned.
417 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000418function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000419 // Default is the first line in the script. Lines in the script is relative
420 // to the offset within the resource.
421 var line = 0;
422 if (!IS_UNDEFINED(opt_line)) {
423 line = opt_line - this.line_offset;
424 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000425
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000426 // Default is first column. If on the first line add the offset within the
427 // resource.
428 var column = opt_column || 0;
429 if (line == 0) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000430 column -= this.column_offset;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431 }
432
433 var offset_position = opt_offset_position || 0;
434 if (line < 0 || column < 0 || offset_position < 0) return null;
435 if (line == 0) {
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000436 return this.locationFromPosition(offset_position + column, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000437 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000438 // Find the line where the offset position is located.
439 var offset_line = this.lineFromPosition(offset_position);
440
441 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
442 return null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000443 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000444
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000445 return this.locationFromPosition(
446 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447 }
448}
449
450
451/**
452 * Get a slice of source code from the script. The boundaries for the slice is
453 * specified in lines.
454 * @param {number} opt_from_line The first line (zero bound) in the slice.
455 * Default is 0
456 * @param {number} opt_to_column The last line (zero bound) in the slice (non
457 * inclusive). Default is the number of lines in the script
458 * @return {SourceSlice} The source slice or null of the parameters where
459 * invalid
460 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000461function ScriptSourceSlice(opt_from_line, opt_to_line) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000462 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
463 : opt_from_line;
464 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
465 : opt_to_line;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466
467 // Adjust according to the offset within the resource.
468 from_line -= this.line_offset;
469 to_line -= this.line_offset;
470 if (from_line < 0) from_line = 0;
471 if (to_line > this.lineCount()) to_line = this.lineCount();
472
iposva@chromium.org245aa852009-02-10 00:49:54 +0000473 // Check parameters.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474 if (from_line >= this.lineCount() ||
475 to_line < 0 ||
476 from_line > to_line) {
477 return null;
478 }
479
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000480 var line_ends = this.line_ends;
481 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
482 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000483
484 // Return a source slice with line numbers re-adjusted to the resource.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000485 return new SourceSlice(this,
486 from_line + this.line_offset,
487 to_line + this.line_offset,
488 from_position, to_position);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489}
490
491
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000492function ScriptSourceLine(opt_line) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493 // Default is the first line in the script. Lines in the script are relative
494 // to the offset within the resource.
495 var line = 0;
496 if (!IS_UNDEFINED(opt_line)) {
497 line = opt_line - this.line_offset;
498 }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000499
500 // Check parameter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 if (line < 0 || this.lineCount() <= line) {
502 return null;
503 }
504
iposva@chromium.org245aa852009-02-10 00:49:54 +0000505 // Return the source line.
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000506 var line_ends = this.line_ends;
507 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
508 var end = line_ends[line];
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000509 return %_CallFunction(this.source, start, end, StringSubstring);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510}
511
512
513/**
514 * Returns the number of source lines.
515 * @return {number}
516 * Number of source lines.
517 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000518function ScriptLineCount() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000519 // Return number of source lines.
520 return this.line_ends.length;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000521}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522
523
524/**
lrn@chromium.org25156de2010-04-06 13:10:27 +0000525 * Returns the name of script if available, contents of sourceURL comment
vegorov@chromium.org42841962010-10-18 11:18:59 +0000526 * otherwise. See
lrn@chromium.org25156de2010-04-06 13:10:27 +0000527 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
528 * for details on using //@ sourceURL comment to identify scritps that don't
529 * have name.
vegorov@chromium.org42841962010-10-18 11:18:59 +0000530 *
lrn@chromium.org25156de2010-04-06 13:10:27 +0000531 * @return {?string} script name if present, value for //@ sourceURL comment
532 * otherwise.
533 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000534function ScriptNameOrSourceURL() {
535 if (this.name) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000536 return this.name;
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000537 }
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000538
539 // The result is cached as on long scripts it takes noticable time to search
540 // for the sourceURL.
541 if (this.hasCachedNameOrSourceURL)
542 return this.cachedNameOrSourceURL;
543 this.hasCachedNameOrSourceURL = true;
544
vegorov@chromium.org42841962010-10-18 11:18:59 +0000545 // TODO(608): the spaces in a regexp below had to be escaped as \040
lrn@chromium.org25156de2010-04-06 13:10:27 +0000546 // because this file is being processed by js2c whose handling of spaces
547 // in regexps is broken. Also, ['"] are excluded from allowed URLs to
548 // avoid matches against sources that invoke evals with sourceURL.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000549 // A better solution would be to detect these special comments in
550 // the scanner/parser.
551 var source = ToString(this.source);
552 var sourceUrlPos = %StringIndexOf(source, "sourceURL=", 0);
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000553 this.cachedNameOrSourceURL = this.name;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000554 if (sourceUrlPos > 4) {
555 var sourceUrlPattern =
556 /\/\/@[\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
557 // Don't reuse lastMatchInfo here, so we create a new array with room
558 // for four captures (array with length one longer than the index
559 // of the fourth capture, where the numbering is zero-based).
560 var matchInfo = new InternalArray(CAPTURE(3) + 1);
561 var match =
562 %_RegExpExec(sourceUrlPattern, source, sourceUrlPos - 4, matchInfo);
563 if (match) {
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000564 this.cachedNameOrSourceURL =
565 SubString(source, matchInfo[CAPTURE(2)], matchInfo[CAPTURE(3)]);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000566 }
567 }
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000568 return this.cachedNameOrSourceURL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000569}
570
571
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000572SetUpLockedPrototype(Script,
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000573 $Array("source", "name", "line_ends", "line_offset", "column_offset",
574 "cachedNameOrSourceURL", "hasCachedNameOrSourceURL" ),
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000575 $Array(
576 "lineFromPosition", ScriptLineFromPosition,
577 "locationFromPosition", ScriptLocationFromPosition,
578 "locationFromLine", ScriptLocationFromLine,
579 "sourceSlice", ScriptSourceSlice,
580 "sourceLine", ScriptSourceLine,
581 "lineCount", ScriptLineCount,
582 "nameOrSourceURL", ScriptNameOrSourceURL
583 )
584);
585
586
lrn@chromium.org25156de2010-04-06 13:10:27 +0000587/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588 * Class for source location. A source location is a position within some
589 * source with the following properties:
590 * script : script object for the source
591 * line : source line number
592 * column : source column within the line
593 * position : position within the source
594 * start : position of start of source context (inclusive)
595 * end : position of end of source context (not inclusive)
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000596 * Source text for the source context is the character interval
597 * [start, end[. In most cases end will point to a newline character.
598 * It might point just past the final position of the source if the last
599 * source line does not end with a newline character.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600 * @param {Script} script The Script object for which this is a location
601 * @param {number} position Source position for the location
602 * @param {number} line The line number for the location
603 * @param {number} column The column within the line for the location
604 * @param {number} start Source position for start of source context
605 * @param {number} end Source position for end of source context
606 * @constructor
607 */
608function SourceLocation(script, position, line, column, start, end) {
609 this.script = script;
610 this.position = position;
611 this.line = line;
612 this.column = column;
613 this.start = start;
614 this.end = end;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000615}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +0000617var kLineLengthLimit = 78;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618
619/**
620 * Restrict source location start and end positions to make the source slice
621 * no more that a certain number of characters wide.
622 * @param {number} opt_limit The with limit of the source text with a default
623 * of 78
624 * @param {number} opt_before The number of characters to prefer before the
625 * position with a default value of 10 less that the limit
626 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000627function SourceLocationRestrict(opt_limit, opt_before) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628 // Find the actual limit to use.
629 var limit;
630 var before;
631 if (!IS_UNDEFINED(opt_limit)) {
632 limit = opt_limit;
633 } else {
634 limit = kLineLengthLimit;
635 }
636 if (!IS_UNDEFINED(opt_before)) {
637 before = opt_before;
638 } else {
639 // If no before is specified center for small limits and perfer more source
640 // before the the position that after for longer limits.
641 if (limit <= 20) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000642 before = $floor(limit / 2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643 } else {
644 before = limit - 10;
645 }
646 }
647 if (before >= limit) {
648 before = limit - 1;
649 }
650
651 // If the [start, end[ interval is too big we restrict
652 // it in one or both ends. We make sure to always produce
653 // restricted intervals of maximum allowed size.
654 if (this.end - this.start > limit) {
655 var start_limit = this.position - before;
656 var end_limit = this.position + limit - before;
657 if (this.start < start_limit && end_limit < this.end) {
658 this.start = start_limit;
659 this.end = end_limit;
660 } else if (this.start < start_limit) {
661 this.start = this.end - limit;
662 } else {
663 this.end = this.start + limit;
664 }
665 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000666}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667
668
669/**
670 * Get the source text for a SourceLocation
671 * @return {String}
672 * Source text for this location.
673 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000674function SourceLocationSourceText() {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000675 return %_CallFunction(this.script.source,
676 this.start,
677 this.end,
678 StringSubstring);
679}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000680
681
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000682SetUpLockedPrototype(SourceLocation,
683 $Array("script", "position", "line", "column", "start", "end"),
684 $Array(
685 "restrict", SourceLocationRestrict,
686 "sourceText", SourceLocationSourceText
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000687 )
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000688);
689
690
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691/**
692 * Class for a source slice. A source slice is a part of a script source with
693 * the following properties:
694 * script : script object for the source
695 * from_line : line number for the first line in the slice
696 * to_line : source line number for the last line in the slice
697 * from_position : position of the first character in the slice
698 * to_position : position of the last character in the slice
699 * The to_line and to_position are not included in the slice, that is the lines
700 * in the slice are [from_line, to_line[. Likewise the characters in the slice
701 * are [from_position, to_position[.
702 * @param {Script} script The Script object for the source slice
703 * @param {number} from_line
704 * @param {number} to_line
705 * @param {number} from_position
706 * @param {number} to_position
707 * @constructor
708 */
709function SourceSlice(script, from_line, to_line, from_position, to_position) {
710 this.script = script;
711 this.from_line = from_line;
712 this.to_line = to_line;
713 this.from_position = from_position;
714 this.to_position = to_position;
715}
716
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717/**
718 * Get the source text for a SourceSlice
719 * @return {String} Source text for this slice. The last line will include
720 * the line terminating characters (if any)
721 */
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000722function SourceSliceSourceText() {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000723 return %_CallFunction(this.script.source,
724 this.from_position,
725 this.to_position,
726 StringSubstring);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000727}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000729SetUpLockedPrototype(SourceSlice,
730 $Array("script", "from_line", "to_line", "from_position", "to_position"),
731 $Array("sourceText", SourceSliceSourceText)
732);
733
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734
735// Returns the offset of the given position within the containing
736// line.
737function GetPositionInLine(message) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000738 var script = %MessageGetScript(message);
739 var start_position = %MessageGetStartPosition(message);
740 var location = script.locationFromPosition(start_position, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000741 if (location == null) return -1;
742 location.restrict();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000743 return start_position - location.start;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000744}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745
746
747function GetStackTraceLine(recv, fun, pos, isGlobal) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000748 return FormatSourcePosition(new CallSite(recv, fun, pos));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000749}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000751// ----------------------------------------------------------------------------
752// Error implementation
753
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000754// Defines accessors for a property that is calculated the first time
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000755// the property is read.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000756function DefineOneShotAccessor(obj, name, fun) {
757 // Note that the accessors consistently operate on 'obj', not 'this'.
758 // Since the object may occur in someone else's prototype chain we
759 // can't rely on 'this' being the same as 'obj'.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000760 var hasBeenSet = false;
761 var value;
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +0000762 var getter = function() {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000763 if (hasBeenSet) {
764 return value;
765 }
766 hasBeenSet = true;
767 value = fun(obj);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000768 return value;
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +0000769 };
770 var setter = function(v) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000771 hasBeenSet = true;
772 value = v;
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +0000773 };
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000774 %DefineOrRedefineAccessorProperty(obj, name, getter, setter, DONT_ENUM);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000775}
776
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000777function CallSite(receiver, fun, pos) {
778 this.receiver = receiver;
779 this.fun = fun;
780 this.pos = pos;
781}
782
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000783function CallSiteGetThis() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000784 return this.receiver;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000785}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000786
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000787function CallSiteGetTypeName() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000788 var constructor = this.receiver.constructor;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000789 if (!constructor) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000790 return %_CallFunction(this.receiver, ObjectToString);
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000791 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000792 var constructorName = constructor.name;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000793 if (!constructorName) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000794 return %_CallFunction(this.receiver, ObjectToString);
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000795 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000796 return constructorName;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000797}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000798
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000799function CallSiteIsToplevel() {
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000800 if (this.receiver == null) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000801 return true;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000802 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000803 return IS_GLOBAL(this.receiver);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000804}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000805
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000806function CallSiteIsEval() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000807 var script = %FunctionGetScript(this.fun);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000808 return script && script.compilation_type == COMPILATION_TYPE_EVAL;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000809}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000810
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000811function CallSiteGetEvalOrigin() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000812 var script = %FunctionGetScript(this.fun);
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000813 return FormatEvalOrigin(script);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000814}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000815
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000816function CallSiteGetScriptNameOrSourceURL() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000817 var script = %FunctionGetScript(this.fun);
818 return script ? script.nameOrSourceURL() : null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000819}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000820
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000821function CallSiteGetFunction() {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000822 return this.fun;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000823}
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000824
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000825function CallSiteGetFunctionName() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000826 // See if the function knows its own name
827 var name = this.fun.name;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000828 if (name) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000829 return name;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000830 } else {
831 return %FunctionGetInferredName(this.fun);
832 }
833 // Maybe this is an evaluation?
834 var script = %FunctionGetScript(this.fun);
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000835 if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000836 return "eval";
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000837 }
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000838 return null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000839}
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000840
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000841function CallSiteGetMethodName() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000842 // See if we can find a unique property on the receiver that holds
843 // this function.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000844 var ownName = this.fun.name;
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000845 if (ownName && this.receiver &&
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000846 (%_CallFunction(this.receiver,
847 ownName,
848 ObjectLookupGetter) === this.fun ||
849 %_CallFunction(this.receiver,
850 ownName,
851 ObjectLookupSetter) === this.fun ||
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000852 this.receiver[ownName] === this.fun)) {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000853 // To handle DontEnum properties we guess that the method has
854 // the same name as the function.
855 return ownName;
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000856 }
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000857 var name = null;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000858 for (var prop in this.receiver) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000859 if (this.receiver.__lookupGetter__(prop) === this.fun ||
860 this.receiver.__lookupSetter__(prop) === this.fun ||
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000861 (!this.receiver.__lookupGetter__(prop) &&
862 this.receiver[prop] === this.fun)) {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000863 // If we find more than one match bail out to avoid confusion.
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000864 if (name) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000865 return null;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000866 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000867 name = prop;
868 }
869 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000870 if (name) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000871 return name;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000872 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000873 return null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000874}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000875
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000876function CallSiteGetFileName() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000877 var script = %FunctionGetScript(this.fun);
878 return script ? script.name : null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000879}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000880
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000881function CallSiteGetLineNumber() {
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000882 if (this.pos == -1) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000883 return null;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000884 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000885 var script = %FunctionGetScript(this.fun);
886 var location = null;
887 if (script) {
888 location = script.locationFromPosition(this.pos, true);
889 }
890 return location ? location.line + 1 : null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000891}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000892
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000893function CallSiteGetColumnNumber() {
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000894 if (this.pos == -1) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000895 return null;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000896 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000897 var script = %FunctionGetScript(this.fun);
898 var location = null;
899 if (script) {
900 location = script.locationFromPosition(this.pos, true);
901 }
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000902 return location ? location.column + 1: null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000903}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000904
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000905function CallSiteIsNative() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000906 var script = %FunctionGetScript(this.fun);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000907 return script ? (script.type == TYPE_NATIVE) : false;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000908}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000909
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000910function CallSiteGetPosition() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000911 return this.pos;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000912}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000913
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000914function CallSiteIsConstructor() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000915 var constructor = this.receiver ? this.receiver.constructor : null;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000916 if (!constructor) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000917 return false;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000918 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000919 return this.fun === constructor;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000920}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000921
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000922SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array(
923 "getThis", CallSiteGetThis,
924 "getTypeName", CallSiteGetTypeName,
925 "isToplevel", CallSiteIsToplevel,
926 "isEval", CallSiteIsEval,
927 "getEvalOrigin", CallSiteGetEvalOrigin,
928 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
929 "getFunction", CallSiteGetFunction,
930 "getFunctionName", CallSiteGetFunctionName,
931 "getMethodName", CallSiteGetMethodName,
932 "getFileName", CallSiteGetFileName,
933 "getLineNumber", CallSiteGetLineNumber,
934 "getColumnNumber", CallSiteGetColumnNumber,
935 "isNative", CallSiteIsNative,
936 "getPosition", CallSiteGetPosition,
937 "isConstructor", CallSiteIsConstructor
938));
939
940
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000941function FormatEvalOrigin(script) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000942 var sourceURL = script.nameOrSourceURL();
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000943 if (sourceURL) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000944 return sourceURL;
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000945 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000946
947 var eval_origin = "eval at ";
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000948 if (script.eval_from_function_name) {
949 eval_origin += script.eval_from_function_name;
950 } else {
951 eval_origin += "<anonymous>";
952 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000953
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000954 var eval_from_script = script.eval_from_script;
955 if (eval_from_script) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000956 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000957 // eval script originated from another eval.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000958 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000959 } else {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000960 // eval script originated from "real" source.
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000961 if (eval_from_script.name) {
962 eval_origin += " (" + eval_from_script.name;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000963 var location = eval_from_script.locationFromPosition(
964 script.eval_from_script_position, true);
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000965 if (location) {
966 eval_origin += ":" + (location.line + 1);
967 eval_origin += ":" + (location.column + 1);
968 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000969 eval_origin += ")";
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000970 } else {
971 eval_origin += " (unknown source)";
972 }
973 }
974 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000975
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000976 return eval_origin;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000977}
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000978
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000979function FormatSourcePosition(frame) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000980 var fileName;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000981 var fileLocation = "";
982 if (frame.isNative()) {
983 fileLocation = "native";
984 } else if (frame.isEval()) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000985 fileName = frame.getScriptNameOrSourceURL();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000986 if (!fileName) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000987 fileLocation = frame.getEvalOrigin();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000988 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000989 } else {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000990 fileName = frame.getFileName();
991 }
992
993 if (fileName) {
994 fileLocation += fileName;
995 var lineNumber = frame.getLineNumber();
996 if (lineNumber != null) {
997 fileLocation += ":" + lineNumber;
998 var columnNumber = frame.getColumnNumber();
999 if (columnNumber) {
1000 fileLocation += ":" + columnNumber;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001001 }
1002 }
1003 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001004
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001005 if (!fileLocation) {
1006 fileLocation = "unknown source";
1007 }
1008 var line = "";
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001009 var functionName = frame.getFunction().name;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001010 var addPrefix = true;
1011 var isConstructor = frame.isConstructor();
1012 var isMethodCall = !(frame.isToplevel() || isConstructor);
1013 if (isMethodCall) {
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +00001014 var methodName = frame.getMethodName();
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001015 line += frame.getTypeName() + ".";
1016 if (functionName) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001017 line += functionName;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001018 if (methodName && (methodName != functionName)) {
1019 line += " [as " + methodName + "]";
1020 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001021 } else {
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001022 line += methodName || "<anonymous>";
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001023 }
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001024 } else if (isConstructor) {
1025 line += "new " + (functionName || "<anonymous>");
1026 } else if (functionName) {
1027 line += functionName;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001028 } else {
1029 line += fileLocation;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001030 addPrefix = false;
1031 }
1032 if (addPrefix) {
1033 line += " (" + fileLocation + ")";
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001034 }
1035 return line;
1036}
1037
1038function FormatStackTrace(error, frames) {
1039 var lines = [];
1040 try {
1041 lines.push(error.toString());
1042 } catch (e) {
1043 try {
1044 lines.push("<error: " + e + ">");
1045 } catch (ee) {
1046 lines.push("<error>");
1047 }
1048 }
1049 for (var i = 0; i < frames.length; i++) {
1050 var frame = frames[i];
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001051 var line;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001052 try {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001053 line = FormatSourcePosition(frame);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001054 } catch (e) {
1055 try {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001056 line = "<error: " + e + ">";
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001057 } catch (ee) {
1058 // Any code that reaches this point is seriously nasty!
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001059 line = "<error>";
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001060 }
1061 }
1062 lines.push(" at " + line);
1063 }
1064 return lines.join("\n");
1065}
1066
1067function FormatRawStackTrace(error, raw_stack) {
1068 var frames = [ ];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001069 for (var i = 0; i < raw_stack.length; i += 4) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001070 var recv = raw_stack[i];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001071 var fun = raw_stack[i + 1];
1072 var code = raw_stack[i + 2];
1073 var pc = raw_stack[i + 3];
1074 var pos = %FunctionGetPositionForOffset(code, pc);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001075 frames.push(new CallSite(recv, fun, pos));
1076 }
1077 if (IS_FUNCTION($Error.prepareStackTrace)) {
1078 return $Error.prepareStackTrace(error, frames);
1079 } else {
1080 return FormatStackTrace(error, frames);
1081 }
1082}
1083
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001084
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001085function captureStackTrace(obj, cons_opt) {
1086 var stackTraceLimit = $Error.stackTraceLimit;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001087 if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001088 if (stackTraceLimit < 0 || stackTraceLimit > 10000) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001089 stackTraceLimit = 10000;
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001090 }
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +00001091 var raw_stack = %CollectStackTrace(obj,
1092 cons_opt ? cons_opt : captureStackTrace,
1093 stackTraceLimit);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001094 DefineOneShotAccessor(obj, 'stack', function (obj) {
1095 return FormatRawStackTrace(obj, raw_stack);
1096 });
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001097}
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001098
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001100function SetUpError() {
1101 // Define special error type constructors.
1102
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00001103 var DefineError = function(f) {
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001104 // Store the error function in both the global object
1105 // and the runtime object. The function is fetched
1106 // from the runtime object when throwing errors from
1107 // within the runtime system to avoid strange side
1108 // effects when overwriting the error functions from
1109 // user code.
1110 var name = f.name;
1111 %SetProperty(global, name, f, DONT_ENUM);
1112 %SetProperty(builtins, '$' + name, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
1113 // Configure the error function.
1114 if (name == 'Error') {
1115 // The prototype of the Error object must itself be an error.
1116 // However, it can't be an instance of the Error object because
1117 // it hasn't been properly configured yet. Instead we create a
1118 // special not-a-true-error-but-close-enough object.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00001119 var ErrorPrototype = function() {};
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001120 %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
1121 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
1122 %FunctionSetPrototype(f, new ErrorPrototype());
1123 } else {
1124 %FunctionSetPrototype(f, new $Error());
1125 }
1126 %FunctionSetInstanceClassName(f, 'Error');
1127 %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
1128 // The name property on the prototype of error objects is not
1129 // specified as being read-one and dont-delete. However, allowing
1130 // overwriting allows leaks of error objects between script blocks
1131 // in the same context in a browser setting. Therefore we fix the
1132 // name.
1133 %SetProperty(f.prototype, "name", name,
1134 DONT_ENUM | DONT_DELETE | READ_ONLY) ;
1135 %SetCode(f, function(m) {
1136 if (%_IsConstructCall()) {
1137 // Define all the expected properties directly on the error
1138 // object. This avoids going through getters and setters defined
1139 // on prototype objects.
1140 %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM);
1141 %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM);
1142 %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM);
1143 if (m === kAddMessageAccessorsMarker) {
1144 // DefineOneShotAccessor always inserts a message property and
1145 // ignores setters.
1146 DefineOneShotAccessor(this, 'message', function (obj) {
1147 return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
1148 });
1149 } else if (!IS_UNDEFINED(m)) {
1150 %IgnoreAttributesAndSetProperty(this,
1151 'message',
1152 ToString(m),
1153 DONT_ENUM);
1154 }
1155 captureStackTrace(this, f);
1156 } else {
1157 return new f(m);
1158 }
1159 });
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001160 %SetNativeFlag(f);
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00001161 };
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001162
1163 DefineError(function Error() { });
1164 DefineError(function TypeError() { });
1165 DefineError(function RangeError() { });
1166 DefineError(function SyntaxError() { });
1167 DefineError(function ReferenceError() { });
1168 DefineError(function EvalError() { });
1169 DefineError(function URIError() { });
1170}
1171
1172SetUpError();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001173
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001174$Error.captureStackTrace = captureStackTrace;
1175
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001176%SetProperty($Error.prototype, 'message', '', DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001178// Global list of error objects visited during ErrorToString. This is
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001179// used to detect cycles in error toString formatting.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00001180var visited_errors = new InternalArray();
1181var cyclic_error_marker = new $Object();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001182
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001183function ErrorToStringDetectCycle(error) {
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001184 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001185 try {
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001186 var type = error.type;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001187 var name = error.name;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001188 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name);
1189 var message = error.message;
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001190 var hasMessage = %_CallFunction(error, "message", ObjectHasOwnProperty);
1191 if (type && !hasMessage) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001192 message = FormatMessage(%NewMessageObject(type, error.arguments));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001193 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001194 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message);
1195 if (name === "") return message;
1196 if (message === "") return name;
1197 return name + ": " + message;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001198 } finally {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001199 visited_errors.length = visited_errors.length - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001200 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001201}
1202
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001203function ErrorToString() {
ulan@chromium.org9a21ec42012-03-06 08:42:24 +00001204 if (!IS_SPEC_OBJECT(this)) {
1205 throw MakeTypeError("called_on_non_object", ["Error.prototype.toString"]);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001206 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001207
1208 try {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001209 return ErrorToStringDetectCycle(this);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001210 } catch(e) {
1211 // If this error message was encountered already return the empty
1212 // string for it instead of recursively formatting it.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001213 if (e === cyclic_error_marker) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001214 return '';
1215 }
1216 throw e;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001217 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001218}
1219
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001220
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001221InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223// Boilerplate for exceptions for stack overflows. Used from
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001224// Isolate::StackOverflow().
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00001225var kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []);