blob: 4a71a61f5c9a21c589faad4be6a3ac4391a26087 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Steve Blocka7e24c12009-10-30 11:49:00 +00005// -------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007var kMessages = {
8 // Error
9 cyclic_proto: ["Cyclic __proto__ value"],
10 code_gen_from_strings: ["%0"],
11 constructor_special_method: ["Class constructor may not be an accessor"],
12 generator_running: ["Generator is already running"],
13 generator_finished: ["Generator has already finished"],
14 // TypeError
15 unexpected_token: ["Unexpected token ", "%0"],
16 unexpected_token_number: ["Unexpected number"],
17 unexpected_token_string: ["Unexpected string"],
18 unexpected_token_identifier: ["Unexpected identifier"],
19 unexpected_reserved: ["Unexpected reserved word"],
20 unexpected_strict_reserved: ["Unexpected strict mode reserved word"],
21 unexpected_eos: ["Unexpected end of input"],
22 malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
23 unterminated_regexp: ["Invalid regular expression: missing /"],
24 regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
25 incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
26 multiple_defaults_in_switch: ["More than one default clause in switch statement"],
27 newline_after_throw: ["Illegal newline after throw"],
28 label_redeclaration: ["Label '", "%0", "' has already been declared"],
29 var_redeclaration: ["Identifier '", "%0", "' has already been declared"],
30 duplicate_template_property: ["Object template has duplicate property '", "%0", "'"],
31 no_catch_or_finally: ["Missing catch or finally after try"],
32 unknown_label: ["Undefined label '", "%0", "'"],
33 uncaught_exception: ["Uncaught ", "%0"],
34 stack_trace: ["Stack Trace:\n", "%0"],
35 called_non_callable: ["%0", " is not a function"],
36 undefined_method: ["Object ", "%1", " has no method '", "%0", "'"],
37 property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"],
38 cannot_convert_to_primitive: ["Cannot convert object to primitive value"],
39 not_constructor: ["%0", " is not a constructor"],
40 not_defined: ["%0", " is not defined"],
41 non_method: ["'super' is referenced from non-method"],
42 unsupported_super: ["Unsupported reference to 'super'"],
43 non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"],
44 non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"],
45 with_expression: ["%0", " has no properties"],
46 illegal_invocation: ["Illegal invocation"],
47 no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
48 apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
49 apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"],
50 toMethod_non_function: ["Function.prototype.toMethod was called on ", "%0", ", which is a ", "%1", " and not a function"],
51 toMethod_non_object: ["Function.prototype.toMethod: home object ", "%0", " is not an object"],
52 invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
53 instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"],
54 instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"],
55 undefined_or_null_to_object: ["Cannot convert undefined or null to object"],
56 reduce_no_initial: ["Reduce of empty array with no initial value"],
57 getter_must_be_callable: ["Getter must be a function: ", "%0"],
58 setter_must_be_callable: ["Setter must be a function: ", "%0"],
59 value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"],
60 proto_object_or_null: ["Object prototype may only be an Object or null: ", "%0"],
61 property_desc_object: ["Property description must be an object: ", "%0"],
62 redefine_disallowed: ["Cannot redefine property: ", "%0"],
63 define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."],
64 non_extensible_proto: ["%0", " is not extensible"],
65 handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
66 proto_non_object: ["Proxy.", "%0", " called with non-object as prototype"],
67 trap_function_expected: ["Proxy.", "%0", " called with non-function for '", "%1", "' trap"],
68 handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
69 handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
70 handler_returned_false: ["Proxy handler ", "%0", " returned false from '", "%1", "' trap"],
71 handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined from '", "%1", "' trap"],
72 proxy_prop_not_configurable: ["Proxy handler ", "%0", " returned non-configurable descriptor for property '", "%2", "' from '", "%1", "' trap"],
73 proxy_non_object_prop_names: ["Trap '", "%1", "' returned non-object ", "%0"],
74 proxy_repeated_prop_name: ["Trap '", "%1", "' returned repeated property name '", "%2", "'"],
75 invalid_weakmap_key: ["Invalid value used as weak map key"],
76 invalid_weakset_value: ["Invalid value used in weak set"],
77 not_date_object: ["this is not a Date object."],
78 observe_non_object: ["Object.", "%0", " cannot ", "%0", " non-object"],
79 observe_non_function: ["Object.", "%0", " cannot deliver to non-function"],
80 observe_callback_frozen: ["Object.observe cannot deliver to a frozen function object"],
81 observe_invalid_accept: ["Object.observe accept must be an array of strings."],
82 observe_type_non_string: ["Invalid changeRecord with non-string 'type' property"],
83 observe_perform_non_string: ["Invalid non-string changeType"],
84 observe_perform_non_function: ["Cannot perform non-function"],
85 observe_notify_non_notifier: ["notify called on non-notifier object"],
86 observe_global_proxy: ["%0", " cannot be called on the global proxy object"],
87 not_typed_array: ["this is not a typed array."],
88 invalid_argument: ["invalid_argument"],
89 data_view_not_array_buffer: ["First argument to DataView constructor must be an ArrayBuffer"],
90 constructor_not_function: ["Constructor ", "%0", " requires 'new'"],
91 not_a_symbol: ["%0", " is not a symbol"],
92 not_a_promise: ["%0", " is not a promise"],
93 resolver_not_a_function: ["Promise resolver ", "%0", " is not a function"],
94 promise_cyclic: ["Chaining cycle detected for promise ", "%0"],
95 array_functions_on_frozen: ["Cannot modify frozen array elements"],
96 array_functions_change_sealed: ["Cannot add/remove sealed array elements"],
97 first_argument_not_regexp: ["First argument to ", "%0", " must not be a regular expression"],
98 not_iterable: ["%0", " is not iterable"],
99 not_an_iterator: ["%0", " is not an iterator"],
100 iterator_result_not_an_object: ["Iterator result ", "%0", " is not an object"],
101 iterator_value_not_an_object: ["Iterator value ", "%0", " is not an entry object"],
102 // RangeError
103 invalid_array_length: ["Invalid array length"],
104 invalid_array_buffer_length: ["Invalid array buffer length"],
105 invalid_string_length: ["Invalid string length"],
106 invalid_typed_array_offset: ["Start offset is too large:"],
107 invalid_typed_array_length: ["Invalid typed array length"],
108 invalid_typed_array_alignment: ["%0", " of ", "%1", " should be a multiple of ", "%2"],
109 typed_array_set_source_too_large:
110 ["Source is too large"],
111 typed_array_set_negative_offset:
112 ["Start offset is negative"],
113 invalid_data_view_offset: ["Start offset is outside the bounds of the buffer"],
114 invalid_data_view_length: ["Invalid data view length"],
115 invalid_data_view_accessor_offset:
116 ["Offset is outside the bounds of the DataView"],
Steve Block1e0659c2011-05-24 12:43:12 +0100117
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 stack_overflow: ["Maximum call stack size exceeded"],
119 invalid_time_value: ["Invalid time value"],
120 invalid_count_value: ["Invalid count value"],
121 invalid_code_point: ["Invalid code point ", "%0"],
122 // ReferenceError
123 invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
124 invalid_lhs_in_for: ["Invalid left-hand side in for-loop"],
125 invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
126 invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
127 // SyntaxError
128 paren_in_arg_string: ["Function arg string contains parenthesis"],
129 not_isvar: ["builtin %IS_VAR: not a variable"],
130 single_function_literal: ["Single function literal required"],
131 invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
132 invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
133 illegal_break: ["Illegal break statement"],
134 illegal_continue: ["Illegal continue statement"],
135 illegal_return: ["Illegal return statement"],
136 error_loading_debugger: ["Error loading debugger"],
137 no_input_to_regexp: ["No input to ", "%0"],
138 invalid_json: ["String '", "%0", "' is not valid JSON"],
139 circular_structure: ["Converting circular structure to JSON"],
140 called_on_non_object: ["%0", " called on non-object"],
141 called_on_null_or_undefined: ["%0", " called on null or undefined"],
142 array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"],
143 object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
144 illegal_access: ["Illegal access"],
145 static_prototype: ["Classes may not have static property named prototype"],
146 strict_mode_with: ["Strict mode code may not include a with statement"],
147 strict_eval_arguments: ["Unexpected eval or arguments in strict mode"],
148 too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"],
149 too_many_parameters: ["Too many parameters in function definition (only 65535 allowed)"],
150 too_many_variables: ["Too many variables declared (only 4194303 allowed)"],
151 strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
152 strict_octal_literal: ["Octal literals are not allowed in strict mode."],
153 strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"],
154 accessor_data_property: ["Object literal may not have data and accessor property with the same name"],
155 accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"],
156 strict_delete: ["Delete of an unqualified identifier in strict mode."],
157 strict_delete_property: ["Cannot delete property '", "%0", "' of ", "%1"],
158 strict_const: ["Use of const in strict mode."],
159 strict_function: ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
160 strict_read_only_property: ["Cannot assign to read only property '", "%0", "' of ", "%1"],
161 strict_cannot_assign: ["Cannot assign to read only '", "%0", "' in strict mode"],
162 strict_poison_pill: ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"],
163 strict_caller: ["Illegal access to a strict mode caller function."],
164 malformed_arrow_function_parameter_list: ["Malformed arrow function parameter list"],
165 generator_poison_pill: ["'caller' and 'arguments' properties may not be accessed on generator functions."],
166 unprotected_let: ["Illegal let declaration in unprotected statement context."],
167 unprotected_const: ["Illegal const declaration in unprotected statement context."],
168 cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"],
169 redef_external_array_element: ["Cannot redefine a property of an object with external array elements"],
170 harmony_const_assign: ["Assignment to constant variable."],
171 symbol_to_string: ["Cannot convert a Symbol value to a string"],
172 symbol_to_primitive: ["Cannot convert a Symbol wrapper object to a primitive value"],
173 symbol_to_number: ["Cannot convert a Symbol value to a number"],
174 invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"],
175 module_type_error: ["Module '", "%0", "' used improperly"],
176 module_export_undefined: ["Export '", "%0", "' is not defined in module"],
177 unexpected_super: ["'super' keyword unexpected here"]
178};
179
180
181function FormatString(format, args) {
Steve Block1e0659c2011-05-24 12:43:12 +0100182 var result = "";
183 var arg_num = 0;
184 for (var i = 0; i < format.length; i++) {
185 var str = format[i];
Ben Murdoch589d6972011-11-30 16:04:58 +0000186 if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) {
187 // Two-char string starts with "%".
188 var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0;
189 if (arg_num < 4) {
190 // str is one of %0, %1, %2 or %3.
Ben Murdoch257744e2011-11-30 15:57:28 +0000191 try {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 str = NoSideEffectToString(args[arg_num]);
Ben Murdoch257744e2011-11-30 15:57:28 +0000193 } catch (e) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 if (%IsJSModule(args[arg_num]))
195 str = "module";
196 else if (IS_SPEC_OBJECT(args[arg_num]))
197 str = "object";
198 else
199 str = "#<error>";
Ben Murdoch257744e2011-11-30 15:57:28 +0000200 }
Steve Block1e0659c2011-05-24 12:43:12 +0100201 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000202 }
Steve Block1e0659c2011-05-24 12:43:12 +0100203 result += str;
Steve Blocka7e24c12009-10-30 11:49:00 +0000204 }
Steve Block1e0659c2011-05-24 12:43:12 +0100205 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000206}
207
208
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209function NoSideEffectToString(obj) {
210 if (IS_STRING(obj)) return obj;
211 if (IS_NUMBER(obj)) return %_NumberToString(obj);
212 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
213 if (IS_UNDEFINED(obj)) return 'undefined';
214 if (IS_NULL(obj)) return 'null';
215 if (IS_FUNCTION(obj)) {
216 var str = %_CallFunction(obj, FunctionToString);
217 if (str.length > 128) {
218 str = %_SubString(str, 0, 111) + "...<omitted>..." +
219 %_SubString(str, str.length - 2, str.length);
220 }
221 return str;
222 }
223 if (IS_SYMBOL(obj)) return %_CallFunction(obj, SymbolToString);
224 if (IS_OBJECT(obj) && %GetDataProperty(obj, "toString") === ObjectToString) {
225 var constructor = %GetDataProperty(obj, "constructor");
226 if (typeof constructor == "function") {
227 var constructorName = constructor.name;
228 if (IS_STRING(constructorName) && constructorName !== "") {
229 return "#<" + constructorName + ">";
230 }
231 }
232 }
233 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
234 return %_CallFunction(obj, ErrorToString);
235 }
236 return %_CallFunction(obj, ObjectToString);
237}
238
239// To determine whether we can safely stringify an object using ErrorToString
240// without the risk of side-effects, we need to check whether the object is
241// either an instance of a native error type (via '%_ClassOf'), or has $Error
242// in its prototype chain and hasn't overwritten 'toString' with something
243// strange and unusual.
244function CanBeSafelyTreatedAsAnErrorObject(obj) {
245 switch (%_ClassOf(obj)) {
246 case 'Error':
247 case 'EvalError':
248 case 'RangeError':
249 case 'ReferenceError':
250 case 'SyntaxError':
251 case 'TypeError':
252 case 'URIError':
253 return true;
254 }
255
256 var objToString = %GetDataProperty(obj, "toString");
257 return obj instanceof $Error && objToString === ErrorToString;
Steve Block1e0659c2011-05-24 12:43:12 +0100258}
Steve Blocka7e24c12009-10-30 11:49:00 +0000259
260
Steve Block1e0659c2011-05-24 12:43:12 +0100261// When formatting internally created error messages, do not
262// invoke overwritten error toString methods but explicitly use
263// the error to string method. This is to avoid leaking error
264// objects between script tags in a browser setting.
265function ToStringCheckErrorObject(obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100267 return %_CallFunction(obj, ErrorToString);
Steve Block1e0659c2011-05-24 12:43:12 +0100268 } else {
269 return ToString(obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000271}
272
273
274function ToDetailString(obj) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000275 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 var constructor = obj.constructor;
Ben Murdoch589d6972011-11-30 16:04:58 +0000277 if (typeof constructor == "function") {
278 var constructorName = constructor.name;
279 if (IS_STRING(constructorName) && constructorName !== "") {
280 return "#<" + constructorName + ">";
281 }
Steve Block1e0659c2011-05-24 12:43:12 +0100282 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000283 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000284 return ToStringCheckErrorObject(obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000285}
286
287
288function MakeGenericError(constructor, type, args) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 if (IS_UNDEFINED(args)) args = [];
290 return new constructor(FormatMessage(type, args));
Steve Blocka7e24c12009-10-30 11:49:00 +0000291}
292
293
294/**
Ben Murdoch589d6972011-11-30 16:04:58 +0000295 * Set up the Script function and constructor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000296 */
297%FunctionSetInstanceClassName(Script, 'Script');
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298%AddNamedProperty(Script.prototype, 'constructor', Script,
299 DONT_ENUM | DONT_DELETE | READ_ONLY);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300%SetCode(Script, function(x) {
301 // Script objects can only be created by the VM.
302 throw new $Error("Not supported");
303});
304
305
306// Helper functions; called from the runtime system.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307function FormatMessage(type, args) {
308 var format = kMessages[type];
309 if (!format) return "<unknown message " + type + ">";
310 return FormatString(format, args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000311}
312
313
314function GetLineNumber(message) {
Steve Block1e0659c2011-05-24 12:43:12 +0100315 var start_position = %MessageGetStartPosition(message);
316 if (start_position == -1) return kNoLineNumberInfo;
317 var script = %MessageGetScript(message);
318 var location = script.locationFromPosition(start_position, true);
Kristian Monsen25f61362010-05-21 11:50:48 +0100319 if (location == null) return kNoLineNumberInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 return location.line + 1;
321}
322
323
324// Returns the source code line containing the given source
325// position, or the empty string if the position is invalid.
326function GetSourceLine(message) {
Steve Block1e0659c2011-05-24 12:43:12 +0100327 var script = %MessageGetScript(message);
328 var start_position = %MessageGetStartPosition(message);
329 var location = script.locationFromPosition(start_position, true);
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 if (location == null) return "";
331 location.restrict();
332 return location.sourceText();
333}
334
335
336function MakeTypeError(type, args) {
337 return MakeGenericError($TypeError, type, args);
338}
339
340
341function MakeRangeError(type, args) {
342 return MakeGenericError($RangeError, type, args);
343}
344
345
346function MakeSyntaxError(type, args) {
347 return MakeGenericError($SyntaxError, type, args);
348}
349
350
351function MakeReferenceError(type, args) {
352 return MakeGenericError($ReferenceError, type, args);
353}
354
355
356function MakeEvalError(type, args) {
357 return MakeGenericError($EvalError, type, args);
358}
359
360
361function MakeError(type, args) {
362 return MakeGenericError($Error, type, args);
363}
364
365/**
366 * Find a line number given a specific source position.
367 * @param {number} position The source position.
368 * @return {number} 0 if input too small, -1 if input too large,
369 else the line number.
370 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000371function ScriptLineFromPosition(position) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 var lower = 0;
373 var upper = this.lineCount() - 1;
Steve Blockd0582a62009-12-15 09:54:21 +0000374 var line_ends = this.line_ends;
Steve Blocka7e24c12009-10-30 11:49:00 +0000375
376 // We'll never find invalid positions so bail right away.
Steve Blockd0582a62009-12-15 09:54:21 +0000377 if (position > line_ends[upper]) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000378 return -1;
379 }
380
381 // This means we don't have to safe-guard indexing line_ends[i - 1].
Steve Blockd0582a62009-12-15 09:54:21 +0000382 if (position <= line_ends[0]) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 return 0;
384 }
385
386 // Binary search to find line # from position range.
387 while (upper >= 1) {
388 var i = (lower + upper) >> 1;
389
Steve Blockd0582a62009-12-15 09:54:21 +0000390 if (position > line_ends[i]) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 lower = i + 1;
Steve Blockd0582a62009-12-15 09:54:21 +0000392 } else if (position <= line_ends[i - 1]) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 upper = i - 1;
394 } else {
395 return i;
396 }
397 }
Steve Block1e0659c2011-05-24 12:43:12 +0100398
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 return -1;
400}
401
402/**
403 * Get information on a specific source position.
404 * @param {number} position The source position
405 * @param {boolean} include_resource_offset Set to true to have the resource
406 * offset added to the location
407 * @return {SourceLocation}
408 * If line is negative or not in the source null is returned.
409 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000410function ScriptLocationFromPosition(position,
411 include_resource_offset) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 var line = this.lineFromPosition(position);
413 if (line == -1) return null;
414
415 // Determine start, end and column.
Steve Blockd0582a62009-12-15 09:54:21 +0000416 var line_ends = this.line_ends;
417 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
418 var end = line_ends[line];
Ben Murdoch589d6972011-11-30 16:04:58 +0000419 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
420 end--;
421 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 var column = position - start;
423
424 // Adjust according to the offset within the resource.
425 if (include_resource_offset) {
426 line += this.line_offset;
427 if (line == this.line_offset) {
428 column += this.column_offset;
429 }
430 }
431
432 return new SourceLocation(this, position, line, column, start, end);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100433}
Steve Blocka7e24c12009-10-30 11:49:00 +0000434
435
436/**
437 * Get information on a specific source line and column possibly offset by a
438 * fixed source position. This function is used to find a source position from
439 * a line and column position. The fixed source position offset is typically
440 * used to find a source position in a function based on a line and column in
441 * the source for the function alone. The offset passed will then be the
442 * start position of the source for the function within the full script source.
443 * @param {number} opt_line The line within the source. Default value is 0
444 * @param {number} opt_column The column in within the line. Default value is 0
445 * @param {number} opt_offset_position The offset from the begining of the
Ben Murdoch589d6972011-11-30 16:04:58 +0000446 * source from where the line and column calculation starts.
447 * Default value is 0
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 * @return {SourceLocation}
449 * If line is negative or not in the source null is returned.
450 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000451function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 // Default is the first line in the script. Lines in the script is relative
453 // to the offset within the resource.
454 var line = 0;
455 if (!IS_UNDEFINED(opt_line)) {
456 line = opt_line - this.line_offset;
457 }
458
459 // Default is first column. If on the first line add the offset within the
460 // resource.
461 var column = opt_column || 0;
462 if (line == 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100463 column -= this.column_offset;
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 }
465
466 var offset_position = opt_offset_position || 0;
467 if (line < 0 || column < 0 || offset_position < 0) return null;
468 if (line == 0) {
469 return this.locationFromPosition(offset_position + column, false);
470 } else {
471 // Find the line where the offset position is located.
472 var offset_line = this.lineFromPosition(offset_position);
473
474 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
475 return null;
476 }
477
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100478 return this.locationFromPosition(
479 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 }
481}
482
483
484/**
485 * Get a slice of source code from the script. The boundaries for the slice is
486 * specified in lines.
487 * @param {number} opt_from_line The first line (zero bound) in the slice.
488 * Default is 0
489 * @param {number} opt_to_column The last line (zero bound) in the slice (non
490 * inclusive). Default is the number of lines in the script
491 * @return {SourceSlice} The source slice or null of the parameters where
492 * invalid
493 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000494function ScriptSourceSlice(opt_from_line, opt_to_line) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100495 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
496 : opt_from_line;
497 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
498 : opt_to_line;
Steve Blocka7e24c12009-10-30 11:49:00 +0000499
500 // Adjust according to the offset within the resource.
501 from_line -= this.line_offset;
502 to_line -= this.line_offset;
503 if (from_line < 0) from_line = 0;
504 if (to_line > this.lineCount()) to_line = this.lineCount();
505
506 // Check parameters.
507 if (from_line >= this.lineCount() ||
508 to_line < 0 ||
509 from_line > to_line) {
510 return null;
511 }
512
Steve Blockd0582a62009-12-15 09:54:21 +0000513 var line_ends = this.line_ends;
514 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
515 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000516
517 // Return a source slice with line numbers re-adjusted to the resource.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 return new SourceSlice(this,
519 from_line + this.line_offset,
520 to_line + this.line_offset,
521 from_position, to_position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000522}
523
524
Ben Murdoch589d6972011-11-30 16:04:58 +0000525function ScriptSourceLine(opt_line) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 // Default is the first line in the script. Lines in the script are relative
527 // to the offset within the resource.
528 var line = 0;
529 if (!IS_UNDEFINED(opt_line)) {
530 line = opt_line - this.line_offset;
531 }
532
533 // Check parameter.
534 if (line < 0 || this.lineCount() <= line) {
535 return null;
536 }
537
538 // Return the source line.
Steve Blockd0582a62009-12-15 09:54:21 +0000539 var line_ends = this.line_ends;
540 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
541 var end = line_ends[line];
Steve Block1e0659c2011-05-24 12:43:12 +0100542 return %_CallFunction(this.source, start, end, StringSubstring);
Steve Blocka7e24c12009-10-30 11:49:00 +0000543}
544
545
546/**
547 * Returns the number of source lines.
548 * @return {number}
549 * Number of source lines.
550 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000551function ScriptLineCount() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000552 // Return number of source lines.
553 return this.line_ends.length;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100554}
Steve Blocka7e24c12009-10-30 11:49:00 +0000555
556
557/**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 * If sourceURL comment is available and script starts at zero returns sourceURL
559 * comment contents. Otherwise, script name is returned. See
Steve Block6ded16b2010-05-10 14:33:55 +0100560 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 * and Source Map Revision 3 proposal for details on using //# sourceURL and
562 * deprecated //@ sourceURL comment to identify scripts that don't have name.
Ben Murdochf87a2032010-10-22 12:50:53 +0100563 *
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 * @return {?string} script name if present, value for //# sourceURL or
565 * deprecated //@ sourceURL comment otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +0100566 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000567function ScriptNameOrSourceURL() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 if (this.line_offset > 0 || this.column_offset > 0) {
Steve Block6ded16b2010-05-10 14:33:55 +0100569 return this.name;
Ben Murdoch589d6972011-11-30 16:04:58 +0000570 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 if (this.source_url) {
572 return this.source_url;
Steve Block44f0eee2011-05-26 01:26:41 +0100573 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000574 return this.name;
Steve Block6ded16b2010-05-10 14:33:55 +0100575}
576
577
Ben Murdoch589d6972011-11-30 16:04:58 +0000578SetUpLockedPrototype(Script,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 $Array("source", "name", "source_url", "source_mapping_url", "line_ends",
580 "line_offset", "column_offset"),
Ben Murdoch589d6972011-11-30 16:04:58 +0000581 $Array(
582 "lineFromPosition", ScriptLineFromPosition,
583 "locationFromPosition", ScriptLocationFromPosition,
584 "locationFromLine", ScriptLocationFromLine,
585 "sourceSlice", ScriptSourceSlice,
586 "sourceLine", ScriptSourceLine,
587 "lineCount", ScriptLineCount,
588 "nameOrSourceURL", ScriptNameOrSourceURL
589 )
590);
591
592
Steve Block6ded16b2010-05-10 14:33:55 +0100593/**
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 * Class for source location. A source location is a position within some
595 * source with the following properties:
596 * script : script object for the source
597 * line : source line number
598 * column : source column within the line
599 * position : position within the source
600 * start : position of start of source context (inclusive)
601 * end : position of end of source context (not inclusive)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100602 * Source text for the source context is the character interval
603 * [start, end[. In most cases end will point to a newline character.
604 * It might point just past the final position of the source if the last
605 * source line does not end with a newline character.
Steve Blocka7e24c12009-10-30 11:49:00 +0000606 * @param {Script} script The Script object for which this is a location
607 * @param {number} position Source position for the location
608 * @param {number} line The line number for the location
609 * @param {number} column The column within the line for the location
610 * @param {number} start Source position for start of source context
611 * @param {number} end Source position for end of source context
612 * @constructor
613 */
614function SourceLocation(script, position, line, column, start, end) {
615 this.script = script;
616 this.position = position;
617 this.line = line;
618 this.column = column;
619 this.start = start;
620 this.end = end;
621}
622
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100623var kLineLengthLimit = 78;
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
625/**
626 * Restrict source location start and end positions to make the source slice
627 * no more that a certain number of characters wide.
628 * @param {number} opt_limit The with limit of the source text with a default
629 * of 78
630 * @param {number} opt_before The number of characters to prefer before the
631 * position with a default value of 10 less that the limit
632 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000633function SourceLocationRestrict(opt_limit, opt_before) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000634 // Find the actual limit to use.
635 var limit;
636 var before;
637 if (!IS_UNDEFINED(opt_limit)) {
638 limit = opt_limit;
639 } else {
640 limit = kLineLengthLimit;
641 }
642 if (!IS_UNDEFINED(opt_before)) {
643 before = opt_before;
644 } else {
645 // If no before is specified center for small limits and perfer more source
646 // before the the position that after for longer limits.
647 if (limit <= 20) {
648 before = $floor(limit / 2);
649 } else {
650 before = limit - 10;
651 }
652 }
653 if (before >= limit) {
654 before = limit - 1;
655 }
656
657 // If the [start, end[ interval is too big we restrict
658 // it in one or both ends. We make sure to always produce
659 // restricted intervals of maximum allowed size.
660 if (this.end - this.start > limit) {
661 var start_limit = this.position - before;
662 var end_limit = this.position + limit - before;
663 if (this.start < start_limit && end_limit < this.end) {
664 this.start = start_limit;
665 this.end = end_limit;
666 } else if (this.start < start_limit) {
667 this.start = this.end - limit;
668 } else {
669 this.end = this.start + limit;
670 }
671 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100672}
Steve Blocka7e24c12009-10-30 11:49:00 +0000673
674
675/**
676 * Get the source text for a SourceLocation
677 * @return {String}
678 * Source text for this location.
679 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000680function SourceLocationSourceText() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100681 return %_CallFunction(this.script.source,
682 this.start,
683 this.end,
684 StringSubstring);
685}
Steve Blocka7e24c12009-10-30 11:49:00 +0000686
687
Ben Murdoch589d6972011-11-30 16:04:58 +0000688SetUpLockedPrototype(SourceLocation,
689 $Array("script", "position", "line", "column", "start", "end"),
690 $Array(
691 "restrict", SourceLocationRestrict,
692 "sourceText", SourceLocationSourceText
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100693 )
Ben Murdoch589d6972011-11-30 16:04:58 +0000694);
695
696
Steve Blocka7e24c12009-10-30 11:49:00 +0000697/**
698 * Class for a source slice. A source slice is a part of a script source with
699 * the following properties:
700 * script : script object for the source
701 * from_line : line number for the first line in the slice
702 * to_line : source line number for the last line in the slice
703 * from_position : position of the first character in the slice
704 * to_position : position of the last character in the slice
705 * The to_line and to_position are not included in the slice, that is the lines
706 * in the slice are [from_line, to_line[. Likewise the characters in the slice
707 * are [from_position, to_position[.
708 * @param {Script} script The Script object for the source slice
709 * @param {number} from_line
710 * @param {number} to_line
711 * @param {number} from_position
712 * @param {number} to_position
713 * @constructor
714 */
715function SourceSlice(script, from_line, to_line, from_position, to_position) {
716 this.script = script;
717 this.from_line = from_line;
718 this.to_line = to_line;
719 this.from_position = from_position;
720 this.to_position = to_position;
721}
722
Steve Blocka7e24c12009-10-30 11:49:00 +0000723/**
724 * Get the source text for a SourceSlice
725 * @return {String} Source text for this slice. The last line will include
726 * the line terminating characters (if any)
727 */
Ben Murdoch589d6972011-11-30 16:04:58 +0000728function SourceSliceSourceText() {
Steve Block1e0659c2011-05-24 12:43:12 +0100729 return %_CallFunction(this.script.source,
730 this.from_position,
731 this.to_position,
732 StringSubstring);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100733}
Steve Blocka7e24c12009-10-30 11:49:00 +0000734
Ben Murdoch589d6972011-11-30 16:04:58 +0000735SetUpLockedPrototype(SourceSlice,
736 $Array("script", "from_line", "to_line", "from_position", "to_position"),
737 $Array("sourceText", SourceSliceSourceText)
738);
739
Steve Blocka7e24c12009-10-30 11:49:00 +0000740
741// Returns the offset of the given position within the containing
742// line.
743function GetPositionInLine(message) {
Steve Block1e0659c2011-05-24 12:43:12 +0100744 var script = %MessageGetScript(message);
745 var start_position = %MessageGetStartPosition(message);
746 var location = script.locationFromPosition(start_position, false);
Steve Blocka7e24c12009-10-30 11:49:00 +0000747 if (location == null) return -1;
748 location.restrict();
Steve Block1e0659c2011-05-24 12:43:12 +0100749 return start_position - location.start;
Steve Blocka7e24c12009-10-30 11:49:00 +0000750}
751
752
753function GetStackTraceLine(recv, fun, pos, isGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754 return new CallSite(recv, fun, pos, false).toString();
Steve Blocka7e24c12009-10-30 11:49:00 +0000755}
756
757// ----------------------------------------------------------------------------
758// Error implementation
759
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760var CallSiteReceiverKey = NEW_PRIVATE_OWN("CallSite#receiver");
761var CallSiteFunctionKey = NEW_PRIVATE_OWN("CallSite#function");
762var CallSitePositionKey = NEW_PRIVATE_OWN("CallSite#position");
763var CallSiteStrictModeKey = NEW_PRIVATE_OWN("CallSite#strict_mode");
Steve Blocka7e24c12009-10-30 11:49:00 +0000764
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765function CallSite(receiver, fun, pos, strict_mode) {
766 SET_PRIVATE(this, CallSiteReceiverKey, receiver);
767 SET_PRIVATE(this, CallSiteFunctionKey, fun);
768 SET_PRIVATE(this, CallSitePositionKey, pos);
769 SET_PRIVATE(this, CallSiteStrictModeKey, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000770}
771
Ben Murdoch589d6972011-11-30 16:04:58 +0000772function CallSiteGetThis() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 return GET_PRIVATE(this, CallSiteStrictModeKey)
774 ? UNDEFINED : GET_PRIVATE(this, CallSiteReceiverKey);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100775}
Steve Blocka7e24c12009-10-30 11:49:00 +0000776
Ben Murdoch589d6972011-11-30 16:04:58 +0000777function CallSiteGetTypeName() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 return GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100779}
Steve Blocka7e24c12009-10-30 11:49:00 +0000780
Ben Murdoch589d6972011-11-30 16:04:58 +0000781function CallSiteIsToplevel() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000782 if (GET_PRIVATE(this, CallSiteReceiverKey) == null) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000783 return true;
Ben Murdoch257744e2011-11-30 15:57:28 +0000784 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785 return IS_GLOBAL(GET_PRIVATE(this, CallSiteReceiverKey));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100786}
Steve Blocka7e24c12009-10-30 11:49:00 +0000787
Ben Murdoch589d6972011-11-30 16:04:58 +0000788function CallSiteIsEval() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Andrei Popescu31002712010-02-23 13:46:05 +0000790 return script && script.compilation_type == COMPILATION_TYPE_EVAL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100791}
Steve Blocka7e24c12009-10-30 11:49:00 +0000792
Ben Murdoch589d6972011-11-30 16:04:58 +0000793function CallSiteGetEvalOrigin() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Steve Blockd0582a62009-12-15 09:54:21 +0000795 return FormatEvalOrigin(script);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100796}
Steve Blocka7e24c12009-10-30 11:49:00 +0000797
Ben Murdoch589d6972011-11-30 16:04:58 +0000798function CallSiteGetScriptNameOrSourceURL() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100800 return script ? script.nameOrSourceURL() : null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100801}
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100802
Ben Murdoch589d6972011-11-30 16:04:58 +0000803function CallSiteGetFunction() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 return GET_PRIVATE(this, CallSiteStrictModeKey)
805 ? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100806}
Steve Blocka7e24c12009-10-30 11:49:00 +0000807
Ben Murdoch589d6972011-11-30 16:04:58 +0000808function CallSiteGetFunctionName() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 // See if the function knows its own name
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810 var name = GET_PRIVATE(this, CallSiteFunctionKey).name;
Steve Blocka7e24c12009-10-30 11:49:00 +0000811 if (name) {
812 return name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000813 }
814 name = %FunctionGetInferredName(GET_PRIVATE(this, CallSiteFunctionKey));
815 if (name) {
816 return name;
Steve Blocka7e24c12009-10-30 11:49:00 +0000817 }
818 // Maybe this is an evaluation?
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Ben Murdoch257744e2011-11-30 15:57:28 +0000820 if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 return "eval";
Ben Murdoch257744e2011-11-30 15:57:28 +0000822 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000823 return null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100824}
Steve Blocka7e24c12009-10-30 11:49:00 +0000825
Ben Murdoch589d6972011-11-30 16:04:58 +0000826function CallSiteGetMethodName() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000827 // See if we can find a unique property on the receiver that holds
828 // this function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
830 var fun = GET_PRIVATE(this, CallSiteFunctionKey);
831 var ownName = fun.name;
832 if (ownName && receiver &&
833 (%_CallFunction(receiver, ownName, ObjectLookupGetter) === fun ||
834 %_CallFunction(receiver, ownName, ObjectLookupSetter) === fun ||
835 (IS_OBJECT(receiver) && %GetDataProperty(receiver, ownName) === fun))) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 // To handle DontEnum properties we guess that the method has
837 // the same name as the function.
838 return ownName;
Iain Merrick75681382010-08-19 15:07:18 +0100839 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000840 var name = null;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 for (var prop in receiver) {
842 if (%_CallFunction(receiver, prop, ObjectLookupGetter) === fun ||
843 %_CallFunction(receiver, prop, ObjectLookupSetter) === fun ||
844 (IS_OBJECT(receiver) && %GetDataProperty(receiver, prop) === fun)) {
Iain Merrick75681382010-08-19 15:07:18 +0100845 // If we find more than one match bail out to avoid confusion.
Ben Murdoch257744e2011-11-30 15:57:28 +0000846 if (name) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000847 return null;
Ben Murdoch257744e2011-11-30 15:57:28 +0000848 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 name = prop;
850 }
851 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000852 if (name) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 return name;
Ben Murdoch257744e2011-11-30 15:57:28 +0000854 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 return null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100856}
Steve Blocka7e24c12009-10-30 11:49:00 +0000857
Ben Murdoch589d6972011-11-30 16:04:58 +0000858function CallSiteGetFileName() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Steve Blocka7e24c12009-10-30 11:49:00 +0000860 return script ? script.name : null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100861}
Steve Blocka7e24c12009-10-30 11:49:00 +0000862
Ben Murdoch589d6972011-11-30 16:04:58 +0000863function CallSiteGetLineNumber() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000865 return null;
Ben Murdoch257744e2011-11-30 15:57:28 +0000866 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 var location = null;
869 if (script) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 location = script.locationFromPosition(
871 GET_PRIVATE(this, CallSitePositionKey), true);
Steve Blocka7e24c12009-10-30 11:49:00 +0000872 }
873 return location ? location.line + 1 : null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100874}
Steve Blocka7e24c12009-10-30 11:49:00 +0000875
Ben Murdoch589d6972011-11-30 16:04:58 +0000876function CallSiteGetColumnNumber() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000878 return null;
Ben Murdoch257744e2011-11-30 15:57:28 +0000879 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000880 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 var location = null;
882 if (script) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 location = script.locationFromPosition(
884 GET_PRIVATE(this, CallSitePositionKey), true);
Steve Blocka7e24c12009-10-30 11:49:00 +0000885 }
Steve Blockd0582a62009-12-15 09:54:21 +0000886 return location ? location.column + 1: null;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100887}
Steve Blocka7e24c12009-10-30 11:49:00 +0000888
Ben Murdoch589d6972011-11-30 16:04:58 +0000889function CallSiteIsNative() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
Andrei Popescu31002712010-02-23 13:46:05 +0000891 return script ? (script.type == TYPE_NATIVE) : false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100892}
Steve Blocka7e24c12009-10-30 11:49:00 +0000893
Ben Murdoch589d6972011-11-30 16:04:58 +0000894function CallSiteGetPosition() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 return GET_PRIVATE(this, CallSitePositionKey);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100896}
Steve Blocka7e24c12009-10-30 11:49:00 +0000897
Ben Murdoch589d6972011-11-30 16:04:58 +0000898function CallSiteIsConstructor() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
900 var constructor = (receiver != null && IS_OBJECT(receiver))
901 ? %GetDataProperty(receiver, "constructor") : null;
902 if (!constructor) return false;
903 return GET_PRIVATE(this, CallSiteFunctionKey) === constructor;
904}
905
906function CallSiteToString() {
907 var fileName;
908 var fileLocation = "";
909 if (this.isNative()) {
910 fileLocation = "native";
911 } else {
912 fileName = this.getScriptNameOrSourceURL();
913 if (!fileName && this.isEval()) {
914 fileLocation = this.getEvalOrigin();
915 fileLocation += ", "; // Expecting source position to follow.
916 }
917
918 if (fileName) {
919 fileLocation += fileName;
920 } else {
921 // Source code does not originate from a file and is not native, but we
922 // can still get the source position inside the source string, e.g. in
923 // an eval string.
924 fileLocation += "<anonymous>";
925 }
926 var lineNumber = this.getLineNumber();
927 if (lineNumber != null) {
928 fileLocation += ":" + lineNumber;
929 var columnNumber = this.getColumnNumber();
930 if (columnNumber) {
931 fileLocation += ":" + columnNumber;
932 }
933 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000934 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935
936 var line = "";
937 var functionName = this.getFunctionName();
938 var addSuffix = true;
939 var isConstructor = this.isConstructor();
940 var isMethodCall = !(this.isToplevel() || isConstructor);
941 if (isMethodCall) {
942 var typeName = GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), true);
943 var methodName = this.getMethodName();
944 if (functionName) {
945 if (typeName &&
946 %_CallFunction(functionName, typeName, StringIndexOfJS) != 0) {
947 line += typeName + ".";
948 }
949 line += functionName;
950 if (methodName &&
951 (%_CallFunction(functionName, "." + methodName, StringIndexOfJS) !=
952 functionName.length - methodName.length - 1)) {
953 line += " [as " + methodName + "]";
954 }
955 } else {
956 line += typeName + "." + (methodName || "<anonymous>");
957 }
958 } else if (isConstructor) {
959 line += "new " + (functionName || "<anonymous>");
960 } else if (functionName) {
961 line += functionName;
962 } else {
963 line += fileLocation;
964 addSuffix = false;
965 }
966 if (addSuffix) {
967 line += " (" + fileLocation + ")";
968 }
969 return line;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100970}
Steve Blocka7e24c12009-10-30 11:49:00 +0000971
Ben Murdoch589d6972011-11-30 16:04:58 +0000972SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array(
973 "getThis", CallSiteGetThis,
974 "getTypeName", CallSiteGetTypeName,
975 "isToplevel", CallSiteIsToplevel,
976 "isEval", CallSiteIsEval,
977 "getEvalOrigin", CallSiteGetEvalOrigin,
978 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
979 "getFunction", CallSiteGetFunction,
980 "getFunctionName", CallSiteGetFunctionName,
981 "getMethodName", CallSiteGetMethodName,
982 "getFileName", CallSiteGetFileName,
983 "getLineNumber", CallSiteGetLineNumber,
984 "getColumnNumber", CallSiteGetColumnNumber,
985 "isNative", CallSiteIsNative,
986 "getPosition", CallSiteGetPosition,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 "isConstructor", CallSiteIsConstructor,
988 "toString", CallSiteToString
Ben Murdoch589d6972011-11-30 16:04:58 +0000989));
990
991
Steve Blockd0582a62009-12-15 09:54:21 +0000992function FormatEvalOrigin(script) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100993 var sourceURL = script.nameOrSourceURL();
Ben Murdoch257744e2011-11-30 15:57:28 +0000994 if (sourceURL) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100995 return sourceURL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000996 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100997
998 var eval_origin = "eval at ";
Steve Blockd0582a62009-12-15 09:54:21 +0000999 if (script.eval_from_function_name) {
1000 eval_origin += script.eval_from_function_name;
1001 } else {
1002 eval_origin += "<anonymous>";
1003 }
Steve Block6ded16b2010-05-10 14:33:55 +01001004
Steve Blockd0582a62009-12-15 09:54:21 +00001005 var eval_from_script = script.eval_from_script;
1006 if (eval_from_script) {
Andrei Popescu31002712010-02-23 13:46:05 +00001007 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
Steve Blockd0582a62009-12-15 09:54:21 +00001008 // eval script originated from another eval.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001009 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
Steve Blockd0582a62009-12-15 09:54:21 +00001010 } else {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001011 // eval script originated from "real" source.
Steve Blockd0582a62009-12-15 09:54:21 +00001012 if (eval_from_script.name) {
1013 eval_origin += " (" + eval_from_script.name;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001014 var location = eval_from_script.locationFromPosition(
1015 script.eval_from_script_position, true);
Steve Blockd0582a62009-12-15 09:54:21 +00001016 if (location) {
1017 eval_origin += ":" + (location.line + 1);
1018 eval_origin += ":" + (location.column + 1);
1019 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001020 eval_origin += ")";
Steve Blockd0582a62009-12-15 09:54:21 +00001021 } else {
1022 eval_origin += " (unknown source)";
1023 }
1024 }
1025 }
Steve Block6ded16b2010-05-10 14:33:55 +01001026
Steve Blockd0582a62009-12-15 09:54:21 +00001027 return eval_origin;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001028}
Steve Blockd0582a62009-12-15 09:54:21 +00001029
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001030
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031function FormatErrorString(error) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001032 try {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 return %_CallFunction(error, ErrorToString);
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 } catch (e) {
1035 try {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 return "<error: " + e + ">";
Steve Blocka7e24c12009-10-30 11:49:00 +00001037 } catch (ee) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 return "<error>";
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 }
1040 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001041}
1042
1043
1044function GetStackFrames(raw_stack) {
1045 var frames = new InternalArray();
1046 var sloppy_frames = raw_stack[0];
1047 for (var i = 1; i < raw_stack.length; i += 4) {
1048 var recv = raw_stack[i];
1049 var fun = raw_stack[i + 1];
1050 var code = raw_stack[i + 2];
1051 var pc = raw_stack[i + 3];
1052 var pos = %FunctionGetPositionForOffset(code, pc);
1053 sloppy_frames--;
1054 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
1055 }
1056 return frames;
1057}
1058
1059
1060// Flag to prevent recursive call of Error.prepareStackTrace.
1061var formatting_custom_stack_trace = false;
1062
1063
1064function FormatStackTrace(obj, raw_stack) {
1065 var frames = GetStackFrames(raw_stack);
1066 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
1067 var array = [];
1068 %MoveArrayContents(frames, array);
1069 formatting_custom_stack_trace = true;
1070 var stack_trace = UNDEFINED;
1071 try {
1072 stack_trace = $Error.prepareStackTrace(obj, array);
1073 } catch (e) {
1074 throw e; // The custom formatting function threw. Rethrow.
1075 } finally {
1076 formatting_custom_stack_trace = false;
1077 }
1078 return stack_trace;
1079 }
1080
1081 var lines = new InternalArray();
1082 lines.push(FormatErrorString(obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001083 for (var i = 0; i < frames.length; i++) {
1084 var frame = frames[i];
1085 var line;
1086 try {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 line = frame.toString();
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 } catch (e) {
1089 try {
1090 line = "<error: " + e + ">";
1091 } catch (ee) {
1092 // Any code that reaches this point is seriously nasty!
1093 line = "<error>";
1094 }
1095 }
1096 lines.push(" at " + line);
1097 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001098 return %_CallFunction(lines, "\n", ArrayJoin);
Steve Blocka7e24c12009-10-30 11:49:00 +00001099}
1100
Steve Blocka7e24c12009-10-30 11:49:00 +00001101
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102function GetTypeName(receiver, requireConstructor) {
1103 var constructor = receiver.constructor;
1104 if (!constructor) {
1105 return requireConstructor ? null :
1106 %_CallFunction(receiver, ObjectToString);
Ben Murdoch257744e2011-11-30 15:57:28 +00001107 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108 var constructorName = constructor.name;
1109 if (!constructorName) {
1110 return requireConstructor ? null :
1111 %_CallFunction(receiver, ObjectToString);
1112 }
1113 return constructorName;
1114}
1115
1116
1117var stack_trace_symbol; // Set during bootstrapping.
1118var formatted_stack_trace_symbol = NEW_PRIVATE_OWN("formatted stack trace");
1119
1120
1121// Format the stack trace if not yet done, and return it.
1122// Cache the formatted stack trace on the holder.
1123var StackTraceGetter = function() {
1124 var formatted_stack_trace = UNDEFINED;
1125 var holder = this;
1126 while (holder) {
1127 var formatted_stack_trace =
1128 GET_PRIVATE(holder, formatted_stack_trace_symbol);
1129 if (IS_UNDEFINED(formatted_stack_trace)) {
1130 // No formatted stack trace available.
1131 var stack_trace = GET_PRIVATE(holder, stack_trace_symbol);
1132 if (IS_UNDEFINED(stack_trace)) {
1133 // Neither formatted nor structured stack trace available.
1134 // Look further up the prototype chain.
1135 holder = %GetPrototype(holder);
1136 continue;
1137 }
1138 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
1139 SET_PRIVATE(holder, stack_trace_symbol, UNDEFINED);
1140 SET_PRIVATE(holder, formatted_stack_trace_symbol, formatted_stack_trace);
1141 }
1142 return formatted_stack_trace;
1143 }
1144 return UNDEFINED;
1145};
1146
1147
1148// If the receiver equals the holder, set the formatted stack trace that the
1149// getter returns.
1150var StackTraceSetter = function(v) {
1151 if (HAS_PRIVATE(this, stack_trace_symbol)) {
1152 SET_PRIVATE(this, stack_trace_symbol, UNDEFINED);
1153 SET_PRIVATE(this, formatted_stack_trace_symbol, v);
1154 }
1155};
1156
1157
1158// Use a dummy function since we do not actually want to capture a stack trace
1159// when constructing the initial Error prototytpes.
1160var captureStackTrace = function captureStackTrace(obj, cons_opt) {
1161 // Define accessors first, as this may fail and throw.
1162 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
1163 set: StackTraceSetter,
1164 configurable: true });
1165 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001166}
Steve Blocka7e24c12009-10-30 11:49:00 +00001167
Steve Blocka7e24c12009-10-30 11:49:00 +00001168
Ben Murdoch589d6972011-11-30 16:04:58 +00001169function SetUpError() {
1170 // Define special error type constructors.
1171
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001172 var DefineError = function(f) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001173 // Store the error function in both the global object
1174 // and the runtime object. The function is fetched
1175 // from the runtime object when throwing errors from
1176 // within the runtime system to avoid strange side
1177 // effects when overwriting the error functions from
1178 // user code.
1179 var name = f.name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 %AddNamedProperty(global, name, f, DONT_ENUM);
1181 %AddNamedProperty(builtins, '$' + name, f,
1182 DONT_ENUM | DONT_DELETE | READ_ONLY);
Ben Murdoch589d6972011-11-30 16:04:58 +00001183 // Configure the error function.
1184 if (name == 'Error') {
1185 // The prototype of the Error object must itself be an error.
1186 // However, it can't be an instance of the Error object because
1187 // it hasn't been properly configured yet. Instead we create a
1188 // special not-a-true-error-but-close-enough object.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001189 var ErrorPrototype = function() {};
Ben Murdoch589d6972011-11-30 16:04:58 +00001190 %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
1191 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
1192 %FunctionSetPrototype(f, new ErrorPrototype());
1193 } else {
1194 %FunctionSetPrototype(f, new $Error());
1195 }
1196 %FunctionSetInstanceClassName(f, 'Error');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
1198 %AddNamedProperty(f.prototype, "name", name, DONT_ENUM);
Ben Murdoch589d6972011-11-30 16:04:58 +00001199 %SetCode(f, function(m) {
1200 if (%_IsConstructCall()) {
1201 // Define all the expected properties directly on the error
1202 // object. This avoids going through getters and setters defined
1203 // on prototype objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 %AddNamedProperty(this, 'stack', UNDEFINED, DONT_ENUM);
1205 if (!IS_UNDEFINED(m)) {
1206 %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM);
Ben Murdoch589d6972011-11-30 16:04:58 +00001207 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001208 try { captureStackTrace(this, f); } catch (e) { }
Ben Murdoch589d6972011-11-30 16:04:58 +00001209 } else {
1210 return new f(m);
1211 }
1212 });
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001213 %SetNativeFlag(f);
1214 };
Ben Murdoch589d6972011-11-30 16:04:58 +00001215
1216 DefineError(function Error() { });
1217 DefineError(function TypeError() { });
1218 DefineError(function RangeError() { });
1219 DefineError(function SyntaxError() { });
1220 DefineError(function ReferenceError() { });
1221 DefineError(function EvalError() { });
1222 DefineError(function URIError() { });
1223}
1224
1225SetUpError();
Steve Blocka7e24c12009-10-30 11:49:00 +00001226
1227$Error.captureStackTrace = captureStackTrace;
1228
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229%AddNamedProperty($Error.prototype, 'message', '', DONT_ENUM);
Steve Blocka7e24c12009-10-30 11:49:00 +00001230
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001231// Global list of error objects visited during ErrorToString. This is
Steve Block1e0659c2011-05-24 12:43:12 +01001232// used to detect cycles in error toString formatting.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001233var visited_errors = new InternalArray();
1234var cyclic_error_marker = new $Object();
Steve Block1e0659c2011-05-24 12:43:12 +01001235
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
1237 var current = error;
1238 // Climb the prototype chain until we find the holder.
1239 while (current && !%HasOwnProperty(current, name)) {
1240 current = %GetPrototype(current);
1241 }
1242 if (IS_NULL(current)) return UNDEFINED;
1243 if (!IS_OBJECT(current)) return error[name];
1244 // If the property is an accessor on one of the predefined errors that can be
1245 // generated statically by the compiler, don't touch it. This is to address
1246 // http://code.google.com/p/chromium/issues/detail?id=69187
1247 var desc = %GetOwnProperty(current, name);
1248 if (desc && desc[IS_ACCESSOR_INDEX]) {
1249 var isName = name === "name";
1250 if (current === $ReferenceError.prototype)
1251 return isName ? "ReferenceError" : UNDEFINED;
1252 if (current === $SyntaxError.prototype)
1253 return isName ? "SyntaxError" : UNDEFINED;
1254 if (current === $TypeError.prototype)
1255 return isName ? "TypeError" : UNDEFINED;
1256 }
1257 // Otherwise, read normally.
1258 return error[name];
1259}
1260
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001261function ErrorToStringDetectCycle(error) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001262 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
Steve Block1e0659c2011-05-24 12:43:12 +01001263 try {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001265 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001267 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message);
1268 if (name === "") return message;
1269 if (message === "") return name;
1270 return name + ": " + message;
Steve Block1e0659c2011-05-24 12:43:12 +01001271 } finally {
1272 visited_errors.length = visited_errors.length - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 }
Steve Block1e0659c2011-05-24 12:43:12 +01001274}
1275
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001276function ErrorToString() {
1277 if (!IS_SPEC_OBJECT(this)) {
1278 throw MakeTypeError("called_on_non_object", ["Error.prototype.toString"]);
Ben Murdoch257744e2011-11-30 15:57:28 +00001279 }
Steve Block1e0659c2011-05-24 12:43:12 +01001280
1281 try {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001282 return ErrorToStringDetectCycle(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001283 } catch(e) {
1284 // If this error message was encountered already return the empty
1285 // string for it instead of recursively formatting it.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001286 if (e === cyclic_error_marker) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001287 return '';
1288 }
1289 throw e;
Steve Block1e0659c2011-05-24 12:43:12 +01001290 }
Ben Murdochb8e0da22011-05-16 14:20:40 +01001291}
1292
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001293
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001294InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001295
Steve Blocka7e24c12009-10-30 11:49:00 +00001296// Boilerplate for exceptions for stack overflows. Used from
Steve Block44f0eee2011-05-26 01:26:41 +01001297// Isolate::StackOverflow().
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298function SetUpStackOverflowBoilerplate() {
1299 var boilerplate = MakeRangeError('stack_overflow', []);
1300
1301 %DefineAccessorPropertyUnchecked(
1302 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM);
1303
1304 return boilerplate;
1305}
1306
1307var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate();