1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // -------------------------------------------------------------------
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"],
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"],
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"],
118 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"],
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"],
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"]
181 function FormatString(format, args) {
184 for (var i = 0; i < format.length; i++) {
186 if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) {
187 // Two-char string starts with "%".
188 var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0;
190 // str is one of %0, %1, %2 or %3.
192 str = NoSideEffectToString(args[arg_num]);
194 if (%IsJSModule(args[arg_num]))
196 else if (IS_SPEC_OBJECT(args[arg_num]))
209 function 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);
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 + ">";
233 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
234 return %_CallFunction(obj, ErrorToString);
236 return %_CallFunction(obj, ObjectToString);
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.
244 function CanBeSafelyTreatedAsAnErrorObject(obj) {
245 switch (%_ClassOf(obj)) {
249 case 'ReferenceError':
256 var objToString = %GetDataProperty(obj, "toString");
257 return obj instanceof $Error && objToString === ErrorToString;
261 // 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.
265 function ToStringCheckErrorObject(obj) {
266 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
267 return %_CallFunction(obj, ErrorToString);
269 return ToString(obj);
274 function ToDetailString(obj) {
275 if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
276 var constructor = obj.constructor;
277 if (typeof constructor == "function") {
278 var constructorName = constructor.name;
279 if (IS_STRING(constructorName) && constructorName !== "") {
280 return "#<" + constructorName + ">";
284 return ToStringCheckErrorObject(obj);
288 function MakeGenericError(constructor, type, args) {
289 if (IS_UNDEFINED(args)) args = [];
290 return new constructor(FormatMessage(type, args));
295 * Set up the Script function and constructor.
297 %FunctionSetInstanceClassName(Script, 'Script');
298 %AddNamedProperty(Script.prototype, 'constructor', Script,
299 DONT_ENUM | DONT_DELETE | READ_ONLY);
300 %SetCode(Script, function(x) {
301 // Script objects can only be created by the VM.
302 throw new $Error("Not supported");
306 // Helper functions; called from the runtime system.
307 function FormatMessage(type, args) {
308 var format = kMessages[type];
309 if (!format) return "<unknown message " + type + ">";
310 return FormatString(format, args);
314 function GetLineNumber(message) {
315 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);
319 if (location == null) return kNoLineNumberInfo;
320 return location.line + 1;
324 // Returns the source code line containing the given source
325 // position, or the empty string if the position is invalid.
326 function GetSourceLine(message) {
327 var script = %MessageGetScript(message);
328 var start_position = %MessageGetStartPosition(message);
329 var location = script.locationFromPosition(start_position, true);
330 if (location == null) return "";
332 return location.sourceText();
336 function MakeTypeError(type, args) {
337 return MakeGenericError($TypeError, type, args);
341 function MakeRangeError(type, args) {
342 return MakeGenericError($RangeError, type, args);
346 function MakeSyntaxError(type, args) {
347 return MakeGenericError($SyntaxError, type, args);
351 function MakeReferenceError(type, args) {
352 return MakeGenericError($ReferenceError, type, args);
356 function MakeEvalError(type, args) {
357 return MakeGenericError($EvalError, type, args);
361 function MakeError(type, args) {
362 return MakeGenericError($Error, type, args);
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.
371 function ScriptLineFromPosition(position) {
373 var upper = this.lineCount() - 1;
374 var line_ends = this.line_ends;
376 // We'll never find invalid positions so bail right away.
377 if (position > line_ends[upper]) {
381 // This means we don't have to safe-guard indexing line_ends[i - 1].
382 if (position <= line_ends[0]) {
386 // Binary search to find line # from position range.
388 var i = (lower + upper) >> 1;
390 if (position > line_ends[i]) {
392 } else if (position <= line_ends[i - 1]) {
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.
410 function ScriptLocationFromPosition(position,
411 include_resource_offset) {
412 var line = this.lineFromPosition(position);
413 if (line == -1) return null;
415 // Determine start, end and column.
416 var line_ends = this.line_ends;
417 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
418 var end = line_ends[line];
419 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
422 var column = position - start;
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;
432 return new SourceLocation(this, position, line, column, start, end);
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
446 * source from where the line and column calculation starts.
448 * @return {SourceLocation}
449 * If line is negative or not in the source null is returned.
451 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
452 // Default is the first line in the script. Lines in the script is relative
453 // to the offset within the resource.
455 if (!IS_UNDEFINED(opt_line)) {
456 line = opt_line - this.line_offset;
459 // Default is first column. If on the first line add the offset within the
461 var column = opt_column || 0;
463 column -= this.column_offset;
466 var offset_position = opt_offset_position || 0;
467 if (line < 0 || column < 0 || offset_position < 0) return null;
469 return this.locationFromPosition(offset_position + column, false);
471 // Find the line where the offset position is located.
472 var offset_line = this.lineFromPosition(offset_position);
474 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
478 return this.locationFromPosition(
479 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
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.
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
494 function ScriptSourceSlice(opt_from_line, opt_to_line) {
495 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
497 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
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();
507 if (from_line >= this.lineCount() ||
509 from_line > to_line) {
513 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;
517 // Return a source slice with line numbers re-adjusted to the resource.
518 return new SourceSlice(this,
519 from_line + this.line_offset,
520 to_line + this.line_offset,
521 from_position, to_position);
525 function ScriptSourceLine(opt_line) {
526 // Default is the first line in the script. Lines in the script are relative
527 // to the offset within the resource.
529 if (!IS_UNDEFINED(opt_line)) {
530 line = opt_line - this.line_offset;
534 if (line < 0 || this.lineCount() <= line) {
538 // Return the source line.
539 var line_ends = this.line_ends;
540 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
541 var end = line_ends[line];
542 return %_CallFunction(this.source, start, end, StringSubstring);
547 * Returns the number of source lines.
549 * Number of source lines.
551 function ScriptLineCount() {
552 // Return number of source lines.
553 return this.line_ends.length;
558 * If sourceURL comment is available and script starts at zero returns sourceURL
559 * comment contents. Otherwise, script name is returned. See
560 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
561 * and Source Map Revision 3 proposal for details on using //# sourceURL and
562 * deprecated //@ sourceURL comment to identify scripts that don't have name.
564 * @return {?string} script name if present, value for //# sourceURL or
565 * deprecated //@ sourceURL comment otherwise.
567 function ScriptNameOrSourceURL() {
568 if (this.line_offset > 0 || this.column_offset > 0) {
571 if (this.source_url) {
572 return this.source_url;
578 SetUpLockedPrototype(Script,
579 $Array("source", "name", "source_url", "source_mapping_url", "line_ends",
580 "line_offset", "column_offset"),
582 "lineFromPosition", ScriptLineFromPosition,
583 "locationFromPosition", ScriptLocationFromPosition,
584 "locationFromLine", ScriptLocationFromLine,
585 "sourceSlice", ScriptSourceSlice,
586 "sourceLine", ScriptSourceLine,
587 "lineCount", ScriptLineCount,
588 "nameOrSourceURL", ScriptNameOrSourceURL
594 * 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)
602 * 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.
606 * @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
614 function SourceLocation(script, position, line, column, start, end) {
615 this.script = script;
616 this.position = position;
618 this.column = column;
623 var kLineLengthLimit = 78;
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
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
633 function SourceLocationRestrict(opt_limit, opt_before) {
634 // Find the actual limit to use.
637 if (!IS_UNDEFINED(opt_limit)) {
640 limit = kLineLengthLimit;
642 if (!IS_UNDEFINED(opt_before)) {
645 // If no before is specified center for small limits and perfer more source
646 // before the the position that after for longer limits.
648 before = $floor(limit / 2);
653 if (before >= limit) {
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;
669 this.end = this.start + limit;
676 * Get the source text for a SourceLocation
678 * Source text for this location.
680 function SourceLocationSourceText() {
681 return %_CallFunction(this.script.source,
688 SetUpLockedPrototype(SourceLocation,
689 $Array("script", "position", "line", "column", "start", "end"),
691 "restrict", SourceLocationRestrict,
692 "sourceText", SourceLocationSourceText
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
715 function 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;
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)
728 function SourceSliceSourceText() {
729 return %_CallFunction(this.script.source,
735 SetUpLockedPrototype(SourceSlice,
736 $Array("script", "from_line", "to_line", "from_position", "to_position"),
737 $Array("sourceText", SourceSliceSourceText)
741 // Returns the offset of the given position within the containing
743 function GetPositionInLine(message) {
744 var script = %MessageGetScript(message);
745 var start_position = %MessageGetStartPosition(message);
746 var location = script.locationFromPosition(start_position, false);
747 if (location == null) return -1;
749 return start_position - location.start;
753 function GetStackTraceLine(recv, fun, pos, isGlobal) {
754 return new CallSite(recv, fun, pos, false).toString();
757 // ----------------------------------------------------------------------------
758 // Error implementation
760 var CallSiteReceiverKey = NEW_PRIVATE_OWN("CallSite#receiver");
761 var CallSiteFunctionKey = NEW_PRIVATE_OWN("CallSite#function");
762 var CallSitePositionKey = NEW_PRIVATE_OWN("CallSite#position");
763 var CallSiteStrictModeKey = NEW_PRIVATE_OWN("CallSite#strict_mode");
765 function 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);
772 function CallSiteGetThis() {
773 return GET_PRIVATE(this, CallSiteStrictModeKey)
774 ? UNDEFINED : GET_PRIVATE(this, CallSiteReceiverKey);
777 function CallSiteGetTypeName() {
778 return GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), false);
781 function CallSiteIsToplevel() {
782 if (GET_PRIVATE(this, CallSiteReceiverKey) == null) {
785 return IS_GLOBAL(GET_PRIVATE(this, CallSiteReceiverKey));
788 function CallSiteIsEval() {
789 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
790 return script && script.compilation_type == COMPILATION_TYPE_EVAL;
793 function CallSiteGetEvalOrigin() {
794 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
795 return FormatEvalOrigin(script);
798 function CallSiteGetScriptNameOrSourceURL() {
799 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
800 return script ? script.nameOrSourceURL() : null;
803 function CallSiteGetFunction() {
804 return GET_PRIVATE(this, CallSiteStrictModeKey)
805 ? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey);
808 function CallSiteGetFunctionName() {
809 // See if the function knows its own name
810 var name = GET_PRIVATE(this, CallSiteFunctionKey).name;
814 name = %FunctionGetInferredName(GET_PRIVATE(this, CallSiteFunctionKey));
818 // Maybe this is an evaluation?
819 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
820 if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
826 function CallSiteGetMethodName() {
827 // See if we can find a unique property on the receiver that holds
829 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))) {
836 // To handle DontEnum properties we guess that the method has
837 // the same name as the function.
841 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)) {
845 // If we find more than one match bail out to avoid confusion.
858 function CallSiteGetFileName() {
859 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
860 return script ? script.name : null;
863 function CallSiteGetLineNumber() {
864 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
867 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
870 location = script.locationFromPosition(
871 GET_PRIVATE(this, CallSitePositionKey), true);
873 return location ? location.line + 1 : null;
876 function CallSiteGetColumnNumber() {
877 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
880 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
883 location = script.locationFromPosition(
884 GET_PRIVATE(this, CallSitePositionKey), true);
886 return location ? location.column + 1: null;
889 function CallSiteIsNative() {
890 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
891 return script ? (script.type == TYPE_NATIVE) : false;
894 function CallSiteGetPosition() {
895 return GET_PRIVATE(this, CallSitePositionKey);
898 function CallSiteIsConstructor() {
899 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;
906 function CallSiteToString() {
908 var fileLocation = "";
909 if (this.isNative()) {
910 fileLocation = "native";
912 fileName = this.getScriptNameOrSourceURL();
913 if (!fileName && this.isEval()) {
914 fileLocation = this.getEvalOrigin();
915 fileLocation += ", "; // Expecting source position to follow.
919 fileLocation += fileName;
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
924 fileLocation += "<anonymous>";
926 var lineNumber = this.getLineNumber();
927 if (lineNumber != null) {
928 fileLocation += ":" + lineNumber;
929 var columnNumber = this.getColumnNumber();
931 fileLocation += ":" + columnNumber;
937 var functionName = this.getFunctionName();
938 var addSuffix = true;
939 var isConstructor = this.isConstructor();
940 var isMethodCall = !(this.isToplevel() || isConstructor);
942 var typeName = GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), true);
943 var methodName = this.getMethodName();
946 %_CallFunction(functionName, typeName, StringIndexOfJS) != 0) {
947 line += typeName + ".";
949 line += functionName;
951 (%_CallFunction(functionName, "." + methodName, StringIndexOfJS) !=
952 functionName.length - methodName.length - 1)) {
953 line += " [as " + methodName + "]";
956 line += typeName + "." + (methodName || "<anonymous>");
958 } else if (isConstructor) {
959 line += "new " + (functionName || "<anonymous>");
960 } else if (functionName) {
961 line += functionName;
963 line += fileLocation;
967 line += " (" + fileLocation + ")";
972 SetUpLockedPrototype(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,
987 "isConstructor", CallSiteIsConstructor,
988 "toString", CallSiteToString
992 function FormatEvalOrigin(script) {
993 var sourceURL = script.nameOrSourceURL();
998 var eval_origin = "eval at ";
999 if (script.eval_from_function_name) {
1000 eval_origin += script.eval_from_function_name;
1002 eval_origin += "<anonymous>";
1005 var eval_from_script = script.eval_from_script;
1006 if (eval_from_script) {
1007 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
1008 // eval script originated from another eval.
1009 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
1011 // eval script originated from "real" source.
1012 if (eval_from_script.name) {
1013 eval_origin += " (" + eval_from_script.name;
1014 var location = eval_from_script.locationFromPosition(
1015 script.eval_from_script_position, true);
1017 eval_origin += ":" + (location.line + 1);
1018 eval_origin += ":" + (location.column + 1);
1022 eval_origin += " (unknown source)";
1031 function FormatErrorString(error) {
1033 return %_CallFunction(error, ErrorToString);
1036 return "<error: " + e + ">";
1044 function 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);
1054 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
1060 // Flag to prevent recursive call of Error.prepareStackTrace.
1061 var formatting_custom_stack_trace = false;
1064 function FormatStackTrace(obj, raw_stack) {
1065 var frames = GetStackFrames(raw_stack);
1066 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
1068 %MoveArrayContents(frames, array);
1069 formatting_custom_stack_trace = true;
1070 var stack_trace = UNDEFINED;
1072 stack_trace = $Error.prepareStackTrace(obj, array);
1074 throw e; // The custom formatting function threw. Rethrow.
1076 formatting_custom_stack_trace = false;
1081 var lines = new InternalArray();
1082 lines.push(FormatErrorString(obj));
1083 for (var i = 0; i < frames.length; i++) {
1084 var frame = frames[i];
1087 line = frame.toString();
1090 line = "<error: " + e + ">";
1092 // Any code that reaches this point is seriously nasty!
1096 lines.push(" at " + line);
1098 return %_CallFunction(lines, "\n", ArrayJoin);
1102 function GetTypeName(receiver, requireConstructor) {
1103 var constructor = receiver.constructor;
1105 return requireConstructor ? null :
1106 %_CallFunction(receiver, ObjectToString);
1108 var constructorName = constructor.name;
1109 if (!constructorName) {
1110 return requireConstructor ? null :
1111 %_CallFunction(receiver, ObjectToString);
1113 return constructorName;
1117 var stack_trace_symbol; // Set during bootstrapping.
1118 var formatted_stack_trace_symbol = NEW_PRIVATE_OWN("formatted stack trace");
1121 // Format the stack trace if not yet done, and return it.
1122 // Cache the formatted stack trace on the holder.
1123 var StackTraceGetter = function() {
1124 var formatted_stack_trace = UNDEFINED;
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);
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);
1142 return formatted_stack_trace;
1148 // If the receiver equals the holder, set the formatted stack trace that the
1150 var 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);
1158 // Use a dummy function since we do not actually want to capture a stack trace
1159 // when constructing the initial Error prototytpes.
1160 var 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);
1169 function SetUpError() {
1170 // Define special error type constructors.
1172 var DefineError = function(f) {
1173 // 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
1180 %AddNamedProperty(global, name, f, DONT_ENUM);
1181 %AddNamedProperty(builtins, '$' + name, f,
1182 DONT_ENUM | DONT_DELETE | READ_ONLY);
1183 // 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.
1189 var ErrorPrototype = function() {};
1190 %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
1191 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
1192 %FunctionSetPrototype(f, new ErrorPrototype());
1194 %FunctionSetPrototype(f, new $Error());
1196 %FunctionSetInstanceClassName(f, 'Error');
1197 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
1198 %AddNamedProperty(f.prototype, "name", name, DONT_ENUM);
1199 %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.
1204 %AddNamedProperty(this, 'stack', UNDEFINED, DONT_ENUM);
1205 if (!IS_UNDEFINED(m)) {
1206 %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM);
1208 try { captureStackTrace(this, f); } catch (e) { }
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() { });
1227 $Error.captureStackTrace = captureStackTrace;
1229 %AddNamedProperty($Error.prototype, 'message', '', DONT_ENUM);
1231 // Global list of error objects visited during ErrorToString. This is
1232 // used to detect cycles in error toString formatting.
1233 var visited_errors = new InternalArray();
1234 var cyclic_error_marker = new $Object();
1236 function 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);
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;
1257 // Otherwise, read normally.
1261 function ErrorToStringDetectCycle(error) {
1262 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
1264 var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name");
1265 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name);
1266 var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message");
1267 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message);
1268 if (name === "") return message;
1269 if (message === "") return name;
1270 return name + ": " + message;
1272 visited_errors.length = visited_errors.length - 1;
1276 function ErrorToString() {
1277 if (!IS_SPEC_OBJECT(this)) {
1278 throw MakeTypeError("called_on_non_object", ["Error.prototype.toString"]);
1282 return ErrorToStringDetectCycle(this);
1284 // If this error message was encountered already return the empty
1285 // string for it instead of recursively formatting it.
1286 if (e === cyclic_error_marker) {
1294 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]);
1296 // Boilerplate for exceptions for stack overflows. Used from
1297 // Isolate::StackOverflow().
1298 function SetUpStackOverflowBoilerplate() {
1299 var boilerplate = MakeRangeError('stack_overflow', []);
1301 %DefineAccessorPropertyUnchecked(
1302 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM);
1307 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate();