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"],
13 generator_running: ["Generator is already running"],
14 unexpected_token: ["Unexpected token ", "%0"],
15 unexpected_token_number: ["Unexpected number"],
16 unexpected_token_string: ["Unexpected string"],
17 unexpected_token_identifier: ["Unexpected identifier"],
18 unexpected_reserved: ["Unexpected reserved word"],
19 unexpected_strict_reserved: ["Unexpected strict mode reserved word"],
20 unexpected_eos: ["Unexpected end of input"],
21 unexpected_template_string: ["Unexpected template string"],
22 malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
23 malformed_regexp_flags: ["Invalid regular expression flags"],
24 unterminated_regexp: ["Invalid regular expression: missing /"],
25 unterminated_template: ["Unterminated template literal"],
26 unterminated_template_expr: ["Missing } in template expression"],
27 regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
28 incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
29 multiple_defaults_in_switch: ["More than one default clause in switch statement"],
30 newline_after_throw: ["Illegal newline after throw"],
31 label_redeclaration: ["Label '", "%0", "' has already been declared"],
32 var_redeclaration: ["Identifier '", "%0", "' has already been declared"],
33 duplicate_template_property: ["Object template has duplicate property '", "%0", "'"],
34 no_catch_or_finally: ["Missing catch or finally after try"],
35 unknown_label: ["Undefined label '", "%0", "'"],
36 uncaught_exception: ["Uncaught ", "%0"],
37 stack_trace: ["Stack Trace:\n", "%0"],
38 called_non_callable: ["%0", " is not a function"],
39 undefined_method: ["Object ", "%1", " has no method '", "%0", "'"],
40 property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"],
41 cannot_convert_to_primitive: ["Cannot convert object to primitive value"],
42 not_constructor: ["%0", " is not a constructor"],
43 not_defined: ["%0", " is not defined"],
44 non_method: ["'super' is referenced from non-method"],
45 unsupported_super: ["Unsupported reference to 'super'"],
46 non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"],
47 non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"],
48 with_expression: ["%0", " has no properties"],
49 illegal_invocation: ["Illegal invocation"],
50 no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
51 apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
52 apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"],
53 flags_getter_non_object: ["RegExp.prototype.flags getter called on non-object ", "%0"],
54 invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
55 instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"],
56 instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"],
57 undefined_or_null_to_object: ["Cannot convert undefined or null to object"],
58 reduce_no_initial: ["Reduce of empty array with no initial value"],
59 getter_must_be_callable: ["Getter must be a function: ", "%0"],
60 setter_must_be_callable: ["Setter must be a function: ", "%0"],
61 value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"],
62 proto_object_or_null: ["Object prototype may only be an Object or null: ", "%0"],
63 property_desc_object: ["Property description must be an object: ", "%0"],
64 redefine_disallowed: ["Cannot redefine property: ", "%0"],
65 define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."],
66 non_extensible_proto: ["%0", " is not extensible"],
67 handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
68 proto_non_object: ["Proxy.", "%0", " called with non-object as prototype"],
69 trap_function_expected: ["Proxy.", "%0", " called with non-function for '", "%1", "' trap"],
70 handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
71 handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
72 handler_returned_false: ["Proxy handler ", "%0", " returned false from '", "%1", "' trap"],
73 handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined from '", "%1", "' trap"],
74 proxy_prop_not_configurable: ["Proxy handler ", "%0", " returned non-configurable descriptor for property '", "%2", "' from '", "%1", "' trap"],
75 proxy_non_object_prop_names: ["Trap '", "%1", "' returned non-object ", "%0"],
76 proxy_repeated_prop_name: ["Trap '", "%1", "' returned repeated property name '", "%2", "'"],
77 invalid_weakmap_key: ["Invalid value used as weak map key"],
78 invalid_weakset_value: ["Invalid value used in weak set"],
79 not_date_object: ["this is not a Date object."],
80 observe_non_object: ["Object.", "%0", " cannot ", "%0", " non-object"],
81 observe_non_function: ["Object.", "%0", " cannot deliver to non-function"],
82 observe_callback_frozen: ["Object.observe cannot deliver to a frozen function object"],
83 observe_invalid_accept: ["Object.observe accept must be an array of strings."],
84 observe_type_non_string: ["Invalid changeRecord with non-string 'type' property"],
85 observe_perform_non_string: ["Invalid non-string changeType"],
86 observe_perform_non_function: ["Cannot perform non-function"],
87 observe_notify_non_notifier: ["notify called on non-notifier object"],
88 observe_global_proxy: ["%0", " cannot be called on the global proxy object"],
89 not_typed_array: ["this is not a typed array."],
90 invalid_argument: ["invalid_argument"],
91 data_view_not_array_buffer: ["First argument to DataView constructor must be an ArrayBuffer"],
92 constructor_not_function: ["Constructor ", "%0", " requires 'new'"],
93 not_a_symbol: ["%0", " is not a symbol"],
94 not_a_promise: ["%0", " is not a promise"],
95 resolver_not_a_function: ["Promise resolver ", "%0", " is not a function"],
96 promise_cyclic: ["Chaining cycle detected for promise ", "%0"],
97 array_functions_on_frozen: ["Cannot modify frozen array elements"],
98 array_functions_change_sealed: ["Cannot add/remove sealed array elements"],
99 first_argument_not_regexp: ["First argument to ", "%0", " must not be a regular expression"],
100 not_iterable: ["%0", " is not iterable"],
101 not_an_iterator: ["%0", " is not an iterator"],
102 iterator_result_not_an_object: ["Iterator result ", "%0", " is not an object"],
103 iterator_value_not_an_object: ["Iterator value ", "%0", " is not an entry object"],
105 invalid_array_length: ["Invalid array length"],
106 invalid_array_buffer_length: ["Invalid array buffer length"],
107 invalid_string_length: ["Invalid string length"],
108 invalid_typed_array_offset: ["Start offset is too large:"],
109 invalid_typed_array_length: ["Invalid typed array length"],
110 invalid_typed_array_alignment: ["%0", " of ", "%1", " should be a multiple of ", "%2"],
111 typed_array_set_source_too_large:
112 ["Source is too large"],
113 typed_array_set_negative_offset:
114 ["Start offset is negative"],
115 invalid_data_view_offset: ["Start offset is outside the bounds of the buffer"],
116 invalid_data_view_length: ["Invalid data view length"],
117 invalid_data_view_accessor_offset:
118 ["Offset is outside the bounds of the DataView"],
120 stack_overflow: ["Maximum call stack size exceeded"],
121 invalid_time_value: ["Invalid time value"],
122 invalid_count_value: ["Invalid count value"],
123 invalid_code_point: ["Invalid code point ", "%0"],
125 invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
126 invalid_lhs_in_for: ["Invalid left-hand side in for-loop"],
127 invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
128 invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
130 paren_in_arg_string: ["Function arg string contains parenthesis"],
131 not_isvar: ["builtin %IS_VAR: not a variable"],
132 single_function_literal: ["Single function literal required"],
133 invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
134 invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
135 illegal_break: ["Illegal break statement"],
136 illegal_continue: ["Illegal continue statement"],
137 illegal_return: ["Illegal return statement"],
138 error_loading_debugger: ["Error loading debugger"],
139 no_input_to_regexp: ["No input to ", "%0"],
140 invalid_json: ["String '", "%0", "' is not valid JSON"],
141 circular_structure: ["Converting circular structure to JSON"],
142 called_on_non_object: ["%0", " called on non-object"],
143 called_on_null_or_undefined: ["%0", " called on null or undefined"],
144 array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"],
145 object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
146 illegal_access: ["Illegal access"],
147 static_prototype: ["Classes may not have static property named prototype"],
148 strict_mode_with: ["Strict mode code may not include a with statement"],
149 strict_eval_arguments: ["Unexpected eval or arguments in strict mode"],
150 too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"],
151 too_many_parameters: ["Too many parameters in function definition (only 65535 allowed)"],
152 too_many_variables: ["Too many variables declared (only 4194303 allowed)"],
153 strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
154 strict_octal_literal: ["Octal literals are not allowed in strict mode."],
155 template_octal_literal: ["Octal literals are not allowed in template strings."],
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 strong_arguments: ["Please don't use 'arguments' in strong mode, use '...args' instead"],
165 strong_equal: ["Please don't use '==' or '!=' in strong mode, use '===' or '!==' instead"],
166 strong_delete: ["Please don't use 'delete' in strong mode, use maps or sets instead"],
167 strong_var: ["Please don't use 'var' in strong mode, use 'let' or 'const' instead"],
168 strong_for_in: ["Please don't use 'for'-'in' loops in strong mode, use 'for'-'of' instead"],
169 strong_empty: ["Please don't use empty sub-statements in strong mode, make them explicit with '{}' instead"],
170 sloppy_lexical: ["Block-scoped declarations (let, const, function, class) not yet supported outside strict mode"],
171 malformed_arrow_function_parameter_list: ["Malformed arrow function parameter list"],
172 generator_poison_pill: ["'caller' and 'arguments' properties may not be accessed on generator functions."],
173 cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"],
174 redef_external_array_element: ["Cannot redefine a property of an object with external array elements"],
175 harmony_const_assign: ["Assignment to constant variable."],
176 symbol_to_string: ["Cannot convert a Symbol value to a string"],
177 symbol_to_primitive: ["Cannot convert a Symbol wrapper object to a primitive value"],
178 symbol_to_number: ["Cannot convert a Symbol value to a number"],
179 invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"],
180 module_export_undefined: ["Export '", "%0", "' is not defined in module"],
181 unexpected_super: ["'super' keyword unexpected here"],
182 extends_value_not_a_function: ["Class extends value ", "%0", " is not a function or null"],
183 prototype_parent_not_an_object: ["Class extends value does not have valid prototype property ", "%0"],
184 duplicate_constructor: ["A class may only have one constructor"],
185 super_constructor_call: ["A 'super' constructor call may only appear as the first statement of a function, and its arguments may not access 'this'. Other forms are not yet supported."],
186 duplicate_proto: ["Duplicate __proto__ fields are not allowed in object literals"],
187 param_after_rest: ["Rest parameter must be last formal parameter"],
188 constructor_noncallable: ["Class constructors cannot be invoked without 'new'"],
189 array_not_subclassable: ["Subclassing Arrays is not currently supported."]
193 function FormatString(format, args) {
196 for (var i = 0; i < format.length; i++) {
198 if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) {
199 // Two-char string starts with "%".
200 var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0;
202 // str is one of %0, %1, %2 or %3.
204 str = NoSideEffectToString(args[arg_num]);
206 if (%IsJSModule(args[arg_num]))
208 else if (IS_SPEC_OBJECT(args[arg_num]))
221 function NoSideEffectToString(obj) {
222 if (IS_STRING(obj)) return obj;
223 if (IS_NUMBER(obj)) return %_NumberToString(obj);
224 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
225 if (IS_UNDEFINED(obj)) return 'undefined';
226 if (IS_NULL(obj)) return 'null';
227 if (IS_FUNCTION(obj)) {
228 var str = %_CallFunction(obj, FunctionToString);
229 if (str.length > 128) {
230 str = %_SubString(str, 0, 111) + "...<omitted>..." +
231 %_SubString(str, str.length - 2, str.length);
235 if (IS_SYMBOL(obj)) return %_CallFunction(obj, SymbolToString);
237 && %GetDataProperty(obj, "toString") === DefaultObjectToString) {
238 var constructor = %GetDataProperty(obj, "constructor");
239 if (typeof constructor == "function") {
240 var constructorName = constructor.name;
241 if (IS_STRING(constructorName) && constructorName !== "") {
242 return "#<" + constructorName + ">";
246 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
247 return %_CallFunction(obj, ErrorToString);
250 return %_CallFunction(obj, NoSideEffectsObjectToString);
253 // To determine whether we can safely stringify an object using ErrorToString
254 // without the risk of side-effects, we need to check whether the object is
255 // either an instance of a native error type (via '%_ClassOf'), or has $Error
256 // in its prototype chain and hasn't overwritten 'toString' with something
257 // strange and unusual.
258 function CanBeSafelyTreatedAsAnErrorObject(obj) {
259 switch (%_ClassOf(obj)) {
263 case 'ReferenceError':
270 var objToString = %GetDataProperty(obj, "toString");
271 return obj instanceof $Error && objToString === ErrorToString;
275 // When formatting internally created error messages, do not
276 // invoke overwritten error toString methods but explicitly use
277 // the error to string method. This is to avoid leaking error
278 // objects between script tags in a browser setting.
279 function ToStringCheckErrorObject(obj) {
280 if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
281 return %_CallFunction(obj, ErrorToString);
283 return ToString(obj);
288 function ToDetailString(obj) {
289 if (obj != null && IS_OBJECT(obj) && obj.toString === DefaultObjectToString) {
290 var constructor = obj.constructor;
291 if (typeof constructor == "function") {
292 var constructorName = constructor.name;
293 if (IS_STRING(constructorName) && constructorName !== "") {
294 return "#<" + constructorName + ">";
298 return ToStringCheckErrorObject(obj);
302 function MakeGenericError(constructor, type, args) {
303 if (IS_UNDEFINED(args)) args = [];
304 return new constructor(FormatMessage(type, args));
309 * Set up the Script function and constructor.
311 %FunctionSetInstanceClassName(Script, 'Script');
312 %AddNamedProperty(Script.prototype, 'constructor', Script,
313 DONT_ENUM | DONT_DELETE | READ_ONLY);
314 %SetCode(Script, function(x) {
315 // Script objects can only be created by the VM.
316 throw new $Error("Not supported");
320 // Helper functions; called from the runtime system.
321 function FormatMessage(type, args) {
322 var format = kMessages[type];
323 if (!format) return "<unknown message " + type + ">";
324 return FormatString(format, args);
328 function GetLineNumber(message) {
329 var start_position = %MessageGetStartPosition(message);
330 if (start_position == -1) return kNoLineNumberInfo;
331 var script = %MessageGetScript(message);
332 var location = script.locationFromPosition(start_position, true);
333 if (location == null) return kNoLineNumberInfo;
334 return location.line + 1;
338 // Returns the source code line containing the given source
339 // position, or the empty string if the position is invalid.
340 function GetSourceLine(message) {
341 var script = %MessageGetScript(message);
342 var start_position = %MessageGetStartPosition(message);
343 var location = script.locationFromPosition(start_position, true);
344 if (location == null) return "";
346 return location.sourceText();
350 function MakeTypeError(type, args) {
351 return MakeGenericError($TypeError, type, args);
355 function MakeRangeError(type, args) {
356 return MakeGenericError($RangeError, type, args);
360 function MakeSyntaxError(type, args) {
361 return MakeGenericError($SyntaxError, type, args);
365 function MakeReferenceError(type, args) {
366 return MakeGenericError($ReferenceError, type, args);
370 function MakeEvalError(type, args) {
371 return MakeGenericError($EvalError, type, args);
375 function MakeError(type, args) {
376 return MakeGenericError($Error, type, args);
380 // The embedded versions are called from unoptimized code, with embedded
381 // arguments. Those arguments cannot be arrays, which are context-dependent.
382 function MakeTypeErrorEmbedded(type, arg) {
383 return MakeGenericError($TypeError, type, [arg]);
387 function MakeSyntaxErrorEmbedded(type, arg) {
388 return MakeGenericError($SyntaxError, type, [arg]);
392 function MakeReferenceErrorEmbedded(type, arg) {
393 return MakeGenericError($ReferenceError, type, [arg]);
397 * Find a line number given a specific source position.
398 * @param {number} position The source position.
399 * @return {number} 0 if input too small, -1 if input too large,
400 else the line number.
402 function ScriptLineFromPosition(position) {
403 var line_ends = this.line_ends;
404 var upper = line_ends.length - 1;
405 if (upper < 0) return -1;
407 // We'll never find invalid positions so bail right away.
408 if (position > line_ends[upper]) return -1;
409 if (position <= line_ends[0]) return 0;
414 var mid = (upper + lower) >> 1;
415 if (position <= line_ends[mid - 1]) {
417 } else if (position > line_ends[mid]){
426 * Get information on a specific source position.
427 * @param {number} position The source position
428 * @param {boolean} include_resource_offset Set to true to have the resource
429 * offset added to the location
430 * @return {SourceLocation}
431 * If line is negative or not in the source null is returned.
433 function ScriptLocationFromPosition(position,
434 include_resource_offset) {
435 var line = this.lineFromPosition(position);
436 if (line == -1) return null;
438 // Determine start, end and column.
439 var line_ends = this.line_ends;
440 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
441 var end = line_ends[line];
442 if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
445 var column = position - start;
447 // Adjust according to the offset within the resource.
448 if (include_resource_offset) {
449 line += this.line_offset;
450 if (line == this.line_offset) {
451 column += this.column_offset;
455 return new SourceLocation(this, position, line, column, start, end);
460 * Get information on a specific source line and column possibly offset by a
461 * fixed source position. This function is used to find a source position from
462 * a line and column position. The fixed source position offset is typically
463 * used to find a source position in a function based on a line and column in
464 * the source for the function alone. The offset passed will then be the
465 * start position of the source for the function within the full script source.
466 * @param {number} opt_line The line within the source. Default value is 0
467 * @param {number} opt_column The column in within the line. Default value is 0
468 * @param {number} opt_offset_position The offset from the begining of the
469 * source from where the line and column calculation starts.
471 * @return {SourceLocation}
472 * If line is negative or not in the source null is returned.
474 function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
475 // Default is the first line in the script. Lines in the script is relative
476 // to the offset within the resource.
478 if (!IS_UNDEFINED(opt_line)) {
479 line = opt_line - this.line_offset;
482 // Default is first column. If on the first line add the offset within the
484 var column = opt_column || 0;
486 column -= this.column_offset;
489 var offset_position = opt_offset_position || 0;
490 if (line < 0 || column < 0 || offset_position < 0) return null;
492 return this.locationFromPosition(offset_position + column, false);
494 // Find the line where the offset position is located.
495 var offset_line = this.lineFromPosition(offset_position);
497 if (offset_line == -1 || offset_line + line >= this.lineCount()) {
501 return this.locationFromPosition(
502 this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
508 * Get a slice of source code from the script. The boundaries for the slice is
509 * specified in lines.
510 * @param {number} opt_from_line The first line (zero bound) in the slice.
512 * @param {number} opt_to_column The last line (zero bound) in the slice (non
513 * inclusive). Default is the number of lines in the script
514 * @return {SourceSlice} The source slice or null of the parameters where
517 function ScriptSourceSlice(opt_from_line, opt_to_line) {
518 var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
520 var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
523 // Adjust according to the offset within the resource.
524 from_line -= this.line_offset;
525 to_line -= this.line_offset;
526 if (from_line < 0) from_line = 0;
527 if (to_line > this.lineCount()) to_line = this.lineCount();
530 if (from_line >= this.lineCount() ||
532 from_line > to_line) {
536 var line_ends = this.line_ends;
537 var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
538 var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
540 // Return a source slice with line numbers re-adjusted to the resource.
541 return new SourceSlice(this,
542 from_line + this.line_offset,
543 to_line + this.line_offset,
544 from_position, to_position);
548 function ScriptSourceLine(opt_line) {
549 // Default is the first line in the script. Lines in the script are relative
550 // to the offset within the resource.
552 if (!IS_UNDEFINED(opt_line)) {
553 line = opt_line - this.line_offset;
557 if (line < 0 || this.lineCount() <= line) {
561 // Return the source line.
562 var line_ends = this.line_ends;
563 var start = line == 0 ? 0 : line_ends[line - 1] + 1;
564 var end = line_ends[line];
565 return %_CallFunction(this.source, start, end, StringSubstring);
570 * Returns the number of source lines.
572 * Number of source lines.
574 function ScriptLineCount() {
575 // Return number of source lines.
576 return this.line_ends.length;
581 * If sourceURL comment is available and script starts at zero returns sourceURL
582 * comment contents. Otherwise, script name is returned. See
583 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
584 * and Source Map Revision 3 proposal for details on using //# sourceURL and
585 * deprecated //@ sourceURL comment to identify scripts that don't have name.
587 * @return {?string} script name if present, value for //# sourceURL or
588 * deprecated //@ sourceURL comment otherwise.
590 function ScriptNameOrSourceURL() {
591 if (this.line_offset > 0 || this.column_offset > 0) {
594 if (this.source_url) {
595 return this.source_url;
601 SetUpLockedPrototype(Script,
602 $Array("source", "name", "source_url", "source_mapping_url", "line_ends",
603 "line_offset", "column_offset"),
605 "lineFromPosition", ScriptLineFromPosition,
606 "locationFromPosition", ScriptLocationFromPosition,
607 "locationFromLine", ScriptLocationFromLine,
608 "sourceSlice", ScriptSourceSlice,
609 "sourceLine", ScriptSourceLine,
610 "lineCount", ScriptLineCount,
611 "nameOrSourceURL", ScriptNameOrSourceURL
617 * Class for source location. A source location is a position within some
618 * source with the following properties:
619 * script : script object for the source
620 * line : source line number
621 * column : source column within the line
622 * position : position within the source
623 * start : position of start of source context (inclusive)
624 * end : position of end of source context (not inclusive)
625 * Source text for the source context is the character interval
626 * [start, end[. In most cases end will point to a newline character.
627 * It might point just past the final position of the source if the last
628 * source line does not end with a newline character.
629 * @param {Script} script The Script object for which this is a location
630 * @param {number} position Source position for the location
631 * @param {number} line The line number for the location
632 * @param {number} column The column within the line for the location
633 * @param {number} start Source position for start of source context
634 * @param {number} end Source position for end of source context
637 function SourceLocation(script, position, line, column, start, end) {
638 this.script = script;
639 this.position = position;
641 this.column = column;
646 var kLineLengthLimit = 78;
649 * Restrict source location start and end positions to make the source slice
650 * no more that a certain number of characters wide.
651 * @param {number} opt_limit The with limit of the source text with a default
653 * @param {number} opt_before The number of characters to prefer before the
654 * position with a default value of 10 less that the limit
656 function SourceLocationRestrict(opt_limit, opt_before) {
657 // Find the actual limit to use.
660 if (!IS_UNDEFINED(opt_limit)) {
663 limit = kLineLengthLimit;
665 if (!IS_UNDEFINED(opt_before)) {
668 // If no before is specified center for small limits and perfer more source
669 // before the the position that after for longer limits.
671 before = $floor(limit / 2);
676 if (before >= limit) {
680 // If the [start, end[ interval is too big we restrict
681 // it in one or both ends. We make sure to always produce
682 // restricted intervals of maximum allowed size.
683 if (this.end - this.start > limit) {
684 var start_limit = this.position - before;
685 var end_limit = this.position + limit - before;
686 if (this.start < start_limit && end_limit < this.end) {
687 this.start = start_limit;
688 this.end = end_limit;
689 } else if (this.start < start_limit) {
690 this.start = this.end - limit;
692 this.end = this.start + limit;
699 * Get the source text for a SourceLocation
701 * Source text for this location.
703 function SourceLocationSourceText() {
704 return %_CallFunction(this.script.source,
711 SetUpLockedPrototype(SourceLocation,
712 $Array("script", "position", "line", "column", "start", "end"),
714 "restrict", SourceLocationRestrict,
715 "sourceText", SourceLocationSourceText
721 * Class for a source slice. A source slice is a part of a script source with
722 * the following properties:
723 * script : script object for the source
724 * from_line : line number for the first line in the slice
725 * to_line : source line number for the last line in the slice
726 * from_position : position of the first character in the slice
727 * to_position : position of the last character in the slice
728 * The to_line and to_position are not included in the slice, that is the lines
729 * in the slice are [from_line, to_line[. Likewise the characters in the slice
730 * are [from_position, to_position[.
731 * @param {Script} script The Script object for the source slice
732 * @param {number} from_line
733 * @param {number} to_line
734 * @param {number} from_position
735 * @param {number} to_position
738 function SourceSlice(script, from_line, to_line, from_position, to_position) {
739 this.script = script;
740 this.from_line = from_line;
741 this.to_line = to_line;
742 this.from_position = from_position;
743 this.to_position = to_position;
747 * Get the source text for a SourceSlice
748 * @return {String} Source text for this slice. The last line will include
749 * the line terminating characters (if any)
751 function SourceSliceSourceText() {
752 return %_CallFunction(this.script.source,
758 SetUpLockedPrototype(SourceSlice,
759 $Array("script", "from_line", "to_line", "from_position", "to_position"),
760 $Array("sourceText", SourceSliceSourceText)
764 // Returns the offset of the given position within the containing
766 function GetPositionInLine(message) {
767 var script = %MessageGetScript(message);
768 var start_position = %MessageGetStartPosition(message);
769 var location = script.locationFromPosition(start_position, false);
770 if (location == null) return -1;
772 return start_position - location.start;
776 function GetStackTraceLine(recv, fun, pos, isGlobal) {
777 return new CallSite(recv, fun, pos, false).toString();
780 // ----------------------------------------------------------------------------
781 // Error implementation
783 var CallSiteReceiverKey = NEW_PRIVATE_OWN("CallSite#receiver");
784 var CallSiteFunctionKey = NEW_PRIVATE_OWN("CallSite#function");
785 var CallSitePositionKey = NEW_PRIVATE_OWN("CallSite#position");
786 var CallSiteStrictModeKey = NEW_PRIVATE_OWN("CallSite#strict_mode");
788 function CallSite(receiver, fun, pos, strict_mode) {
789 SET_PRIVATE(this, CallSiteReceiverKey, receiver);
790 SET_PRIVATE(this, CallSiteFunctionKey, fun);
791 SET_PRIVATE(this, CallSitePositionKey, pos);
792 SET_PRIVATE(this, CallSiteStrictModeKey, strict_mode);
795 function CallSiteGetThis() {
796 return GET_PRIVATE(this, CallSiteStrictModeKey)
797 ? UNDEFINED : GET_PRIVATE(this, CallSiteReceiverKey);
800 function CallSiteGetTypeName() {
801 return GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), false);
804 function CallSiteIsToplevel() {
805 if (GET_PRIVATE(this, CallSiteReceiverKey) == null) {
808 return IS_GLOBAL(GET_PRIVATE(this, CallSiteReceiverKey));
811 function CallSiteIsEval() {
812 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
813 return script && script.compilation_type == COMPILATION_TYPE_EVAL;
816 function CallSiteGetEvalOrigin() {
817 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
818 return FormatEvalOrigin(script);
821 function CallSiteGetScriptNameOrSourceURL() {
822 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
823 return script ? script.nameOrSourceURL() : null;
826 function CallSiteGetFunction() {
827 return GET_PRIVATE(this, CallSiteStrictModeKey)
828 ? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey);
831 function CallSiteGetFunctionName() {
832 // See if the function knows its own name
833 var name = GET_PRIVATE(this, CallSiteFunctionKey).name;
837 name = %FunctionGetInferredName(GET_PRIVATE(this, CallSiteFunctionKey));
841 // Maybe this is an evaluation?
842 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
843 if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
849 function CallSiteGetMethodName() {
850 // See if we can find a unique property on the receiver that holds
852 var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
853 var fun = GET_PRIVATE(this, CallSiteFunctionKey);
854 var ownName = fun.name;
855 if (ownName && receiver &&
856 (%_CallFunction(receiver, ownName, ObjectLookupGetter) === fun ||
857 %_CallFunction(receiver, ownName, ObjectLookupSetter) === fun ||
858 (IS_OBJECT(receiver) && %GetDataProperty(receiver, ownName) === fun))) {
859 // To handle DontEnum properties we guess that the method has
860 // the same name as the function.
864 for (var prop in receiver) {
865 if (%_CallFunction(receiver, prop, ObjectLookupGetter) === fun ||
866 %_CallFunction(receiver, prop, ObjectLookupSetter) === fun ||
867 (IS_OBJECT(receiver) && %GetDataProperty(receiver, prop) === fun)) {
868 // If we find more than one match bail out to avoid confusion.
881 function CallSiteGetFileName() {
882 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
883 return script ? script.name : null;
886 function CallSiteGetLineNumber() {
887 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
890 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
893 location = script.locationFromPosition(
894 GET_PRIVATE(this, CallSitePositionKey), true);
896 return location ? location.line + 1 : null;
899 function CallSiteGetColumnNumber() {
900 if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
903 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
906 location = script.locationFromPosition(
907 GET_PRIVATE(this, CallSitePositionKey), true);
909 return location ? location.column + 1: null;
912 function CallSiteIsNative() {
913 var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
914 return script ? (script.type == TYPE_NATIVE) : false;
917 function CallSiteGetPosition() {
918 return GET_PRIVATE(this, CallSitePositionKey);
921 function CallSiteIsConstructor() {
922 var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
923 var constructor = (receiver != null && IS_OBJECT(receiver))
924 ? %GetDataProperty(receiver, "constructor") : null;
925 if (!constructor) return false;
926 return GET_PRIVATE(this, CallSiteFunctionKey) === constructor;
929 function CallSiteToString() {
931 var fileLocation = "";
932 if (this.isNative()) {
933 fileLocation = "native";
935 fileName = this.getScriptNameOrSourceURL();
936 if (!fileName && this.isEval()) {
937 fileLocation = this.getEvalOrigin();
938 fileLocation += ", "; // Expecting source position to follow.
942 fileLocation += fileName;
944 // Source code does not originate from a file and is not native, but we
945 // can still get the source position inside the source string, e.g. in
947 fileLocation += "<anonymous>";
949 var lineNumber = this.getLineNumber();
950 if (lineNumber != null) {
951 fileLocation += ":" + lineNumber;
952 var columnNumber = this.getColumnNumber();
954 fileLocation += ":" + columnNumber;
960 var functionName = this.getFunctionName();
961 var addSuffix = true;
962 var isConstructor = this.isConstructor();
963 var isMethodCall = !(this.isToplevel() || isConstructor);
965 var typeName = GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), true);
966 var methodName = this.getMethodName();
969 %_CallFunction(functionName, typeName, StringIndexOfJS) != 0) {
970 line += typeName + ".";
972 line += functionName;
974 (%_CallFunction(functionName, "." + methodName, StringIndexOfJS) !=
975 functionName.length - methodName.length - 1)) {
976 line += " [as " + methodName + "]";
979 line += typeName + "." + (methodName || "<anonymous>");
981 } else if (isConstructor) {
982 line += "new " + (functionName || "<anonymous>");
983 } else if (functionName) {
984 line += functionName;
986 line += fileLocation;
990 line += " (" + fileLocation + ")";
995 SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array(
996 "getThis", CallSiteGetThis,
997 "getTypeName", CallSiteGetTypeName,
998 "isToplevel", CallSiteIsToplevel,
999 "isEval", CallSiteIsEval,
1000 "getEvalOrigin", CallSiteGetEvalOrigin,
1001 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
1002 "getFunction", CallSiteGetFunction,
1003 "getFunctionName", CallSiteGetFunctionName,
1004 "getMethodName", CallSiteGetMethodName,
1005 "getFileName", CallSiteGetFileName,
1006 "getLineNumber", CallSiteGetLineNumber,
1007 "getColumnNumber", CallSiteGetColumnNumber,
1008 "isNative", CallSiteIsNative,
1009 "getPosition", CallSiteGetPosition,
1010 "isConstructor", CallSiteIsConstructor,
1011 "toString", CallSiteToString
1015 function FormatEvalOrigin(script) {
1016 var sourceURL = script.nameOrSourceURL();
1021 var eval_origin = "eval at ";
1022 if (script.eval_from_function_name) {
1023 eval_origin += script.eval_from_function_name;
1025 eval_origin += "<anonymous>";
1028 var eval_from_script = script.eval_from_script;
1029 if (eval_from_script) {
1030 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
1031 // eval script originated from another eval.
1032 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
1034 // eval script originated from "real" source.
1035 if (eval_from_script.name) {
1036 eval_origin += " (" + eval_from_script.name;
1037 var location = eval_from_script.locationFromPosition(
1038 script.eval_from_script_position, true);
1040 eval_origin += ":" + (location.line + 1);
1041 eval_origin += ":" + (location.column + 1);
1045 eval_origin += " (unknown source)";
1054 function FormatErrorString(error) {
1056 return %_CallFunction(error, ErrorToString);
1059 return "<error: " + e + ">";
1067 function GetStackFrames(raw_stack) {
1068 var frames = new InternalArray();
1069 var sloppy_frames = raw_stack[0];
1070 for (var i = 1; i < raw_stack.length; i += 4) {
1071 var recv = raw_stack[i];
1072 var fun = raw_stack[i + 1];
1073 var code = raw_stack[i + 2];
1074 var pc = raw_stack[i + 3];
1075 var pos = %FunctionGetPositionForOffset(code, pc);
1077 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
1083 // Flag to prevent recursive call of Error.prepareStackTrace.
1084 var formatting_custom_stack_trace = false;
1087 function FormatStackTrace(obj, raw_stack) {
1088 var frames = GetStackFrames(raw_stack);
1089 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
1091 %MoveArrayContents(frames, array);
1092 formatting_custom_stack_trace = true;
1093 var stack_trace = UNDEFINED;
1095 stack_trace = $Error.prepareStackTrace(obj, array);
1097 throw e; // The custom formatting function threw. Rethrow.
1099 formatting_custom_stack_trace = false;
1104 var lines = new InternalArray();
1105 lines.push(FormatErrorString(obj));
1106 for (var i = 0; i < frames.length; i++) {
1107 var frame = frames[i];
1110 line = frame.toString();
1113 line = "<error: " + e + ">";
1115 // Any code that reaches this point is seriously nasty!
1119 lines.push(" at " + line);
1121 return %_CallFunction(lines, "\n", ArrayJoin);
1125 function GetTypeName(receiver, requireConstructor) {
1126 var constructor = receiver.constructor;
1128 return requireConstructor ? null :
1129 %_CallFunction(receiver, NoSideEffectsObjectToString);
1131 var constructorName = constructor.name;
1132 if (!constructorName) {
1133 return requireConstructor ? null :
1134 %_CallFunction(receiver, NoSideEffectsObjectToString);
1136 return constructorName;
1140 var stack_trace_symbol; // Set during bootstrapping.
1141 var formatted_stack_trace_symbol = NEW_PRIVATE_OWN("formatted stack trace");
1144 // Format the stack trace if not yet done, and return it.
1145 // Cache the formatted stack trace on the holder.
1146 var StackTraceGetter = function() {
1147 var formatted_stack_trace = UNDEFINED;
1150 var formatted_stack_trace =
1151 GET_PRIVATE(holder, formatted_stack_trace_symbol);
1152 if (IS_UNDEFINED(formatted_stack_trace)) {
1153 // No formatted stack trace available.
1154 var stack_trace = GET_PRIVATE(holder, stack_trace_symbol);
1155 if (IS_UNDEFINED(stack_trace)) {
1156 // Neither formatted nor structured stack trace available.
1157 // Look further up the prototype chain.
1158 holder = %_GetPrototype(holder);
1161 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
1162 SET_PRIVATE(holder, stack_trace_symbol, UNDEFINED);
1163 SET_PRIVATE(holder, formatted_stack_trace_symbol, formatted_stack_trace);
1165 return formatted_stack_trace;
1171 // If the receiver equals the holder, set the formatted stack trace that the
1173 var StackTraceSetter = function(v) {
1174 if (HAS_PRIVATE(this, stack_trace_symbol)) {
1175 SET_PRIVATE(this, stack_trace_symbol, UNDEFINED);
1176 SET_PRIVATE(this, formatted_stack_trace_symbol, v);
1181 // Use a dummy function since we do not actually want to capture a stack trace
1182 // when constructing the initial Error prototytpes.
1183 var captureStackTrace = function captureStackTrace(obj, cons_opt) {
1184 // Define accessors first, as this may fail and throw.
1185 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
1186 set: StackTraceSetter,
1187 configurable: true });
1188 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
1192 function SetUpError() {
1193 // Define special error type constructors.
1195 var DefineError = function(f) {
1196 // Store the error function in both the global object
1197 // and the runtime object. The function is fetched
1198 // from the runtime object when throwing errors from
1199 // within the runtime system to avoid strange side
1200 // effects when overwriting the error functions from
1203 %AddNamedProperty(global, name, f, DONT_ENUM);
1204 %AddNamedProperty(builtins, '$' + name, f,
1205 DONT_ENUM | DONT_DELETE | READ_ONLY);
1206 // Configure the error function.
1207 if (name == 'Error') {
1208 // The prototype of the Error object must itself be an error.
1209 // However, it can't be an instance of the Error object because
1210 // it hasn't been properly configured yet. Instead we create a
1211 // special not-a-true-error-but-close-enough object.
1212 var ErrorPrototype = function() {};
1213 %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
1214 %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
1215 %FunctionSetPrototype(f, new ErrorPrototype());
1217 %FunctionSetPrototype(f, new $Error());
1219 %FunctionSetInstanceClassName(f, 'Error');
1220 %AddNamedProperty(f.prototype, 'constructor', f, DONT_ENUM);
1221 %AddNamedProperty(f.prototype, "name", name, DONT_ENUM);
1222 %SetCode(f, function(m) {
1223 if (%_IsConstructCall()) {
1224 try { captureStackTrace(this, f); } catch (e) { }
1225 // Define all the expected properties directly on the error
1226 // object. This avoids going through getters and setters defined
1227 // on prototype objects.
1228 if (!IS_UNDEFINED(m)) {
1229 %AddNamedProperty(this, 'message', ToString(m), DONT_ENUM);
1238 DefineError(function Error() { });
1239 DefineError(function TypeError() { });
1240 DefineError(function RangeError() { });
1241 DefineError(function SyntaxError() { });
1242 DefineError(function ReferenceError() { });
1243 DefineError(function EvalError() { });
1244 DefineError(function URIError() { });
1249 $Error.captureStackTrace = captureStackTrace;
1251 %AddNamedProperty($Error.prototype, 'message', '', DONT_ENUM);
1253 // Global list of error objects visited during ErrorToString. This is
1254 // used to detect cycles in error toString formatting.
1255 var visited_errors = new InternalArray();
1256 var cyclic_error_marker = new $Object();
1258 function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
1259 var current = error;
1260 // Climb the prototype chain until we find the holder.
1261 while (current && !%HasOwnProperty(current, name)) {
1262 current = %_GetPrototype(current);
1264 if (IS_NULL(current)) return UNDEFINED;
1265 if (!IS_OBJECT(current)) return error[name];
1266 // If the property is an accessor on one of the predefined errors that can be
1267 // generated statically by the compiler, don't touch it. This is to address
1268 // http://code.google.com/p/chromium/issues/detail?id=69187
1269 var desc = %GetOwnProperty(current, name);
1270 if (desc && desc[IS_ACCESSOR_INDEX]) {
1271 var isName = name === "name";
1272 if (current === $ReferenceError.prototype)
1273 return isName ? "ReferenceError" : UNDEFINED;
1274 if (current === $SyntaxError.prototype)
1275 return isName ? "SyntaxError" : UNDEFINED;
1276 if (current === $TypeError.prototype)
1277 return isName ? "TypeError" : UNDEFINED;
1279 // Otherwise, read normally.
1283 function ErrorToStringDetectCycle(error) {
1284 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
1286 var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name");
1287 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name);
1288 var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message");
1289 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message);
1290 if (name === "") return message;
1291 if (message === "") return name;
1292 return name + ": " + message;
1294 visited_errors.length = visited_errors.length - 1;
1298 function ErrorToString() {
1299 if (!IS_SPEC_OBJECT(this)) {
1300 throw MakeTypeError("called_on_non_object", ["Error.prototype.toString"]);
1304 return ErrorToStringDetectCycle(this);
1306 // If this error message was encountered already return the empty
1307 // string for it instead of recursively formatting it.
1308 if (e === cyclic_error_marker) {
1316 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]);
1318 // Boilerplate for exceptions for stack overflows. Used from
1319 // Isolate::StackOverflow().
1320 function SetUpStackOverflowBoilerplate() {
1321 var boilerplate = MakeRangeError('stack_overflow', []);
1323 %DefineAccessorPropertyUnchecked(
1324 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM);
1329 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate();