messages.js revision 44f0eee88ff00398ff7f715fab053374d808c90d
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------
303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Matches Script::Type from objects.h
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar TYPE_NATIVE = 0;
333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar TYPE_EXTENSION = 1;
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar TYPE_NORMAL = 2;
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Matches Script::CompilationType from objects.h
373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar COMPILATION_TYPE_HOST = 0;
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar COMPILATION_TYPE_EVAL = 1;
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvar COMPILATION_TYPE_JSON = 2;
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Matches Messages::kNoLineNumberInfo from v8.h
4225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenvar kNoLineNumberInfo = 0;
4325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If this object gets passed to an error constructor the error will
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// get an accessor for .message that constructs a descriptive error
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// message on access.
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar kAddMessageAccessorsMarker = { };
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvar kMessages = 0;
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvar kReplacementMarkers = [ "%0", "%1", "%2", "%3" ];
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction FormatString(format, message) {
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var args = %MessageGetArguments(message);
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var result = "";
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var arg_num = 0;
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (var i = 0; i < format.length; i++) {
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    var str = format[i];
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (format[i] !== kReplacementMarkers[arg_num]) continue;
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      try {
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        str = ToDetailString(args[arg_num]);
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } catch (e) {
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        str = "#<error>";
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    result += str;
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return result;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// To check if something is a native error we need to check the
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// concrete native error types. It is not enough to check "obj
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// instanceof $Error" because user code can replace
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// NativeError.prototype.__proto__. User code cannot replace
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// NativeError.prototype though and therefore this is a safe test.
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction IsNativeErrorObject(obj) {
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return (obj instanceof $Error) ||
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $EvalError) ||
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $RangeError) ||
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $ReferenceError) ||
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $SyntaxError) ||
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $TypeError) ||
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (obj instanceof $URIError);
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// When formatting internally created error messages, do not
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// invoke overwritten error toString methods but explicitly use
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the error to string method. This is to avoid leaking error
921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// objects between script tags in a browser setting.
931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction ToStringCheckErrorObject(obj) {
941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (IsNativeErrorObject(obj)) {
951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return %_CallFunction(obj, errorToString);
961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return ToString(obj);
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ToDetailString(obj) {
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var constructor = obj.constructor;
1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (!constructor) return ToStringCheckErrorObject(obj);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var constructorName = constructor.name;
1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (!constructorName || !IS_STRING(constructorName)) {
1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return ToStringCheckErrorObject(obj);
1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return "#<" + constructorName + ">";
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return ToStringCheckErrorObject(obj);
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeGenericError(constructor, type, args) {
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IS_UNDEFINED(args)) {
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    args = [];
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var e = new constructor(kAddMessageAccessorsMarker);
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  e.type = type;
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  e.arguments = args;
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return e;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Setup the Script function and constructor.
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%FunctionSetInstanceClassName(Script, 'Script');
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%SetCode(Script, function(x) {
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Script objects can only be created by the VM.
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  throw new $Error("Not supported");
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block});
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper functions; called from the runtime system.
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction FormatMessage(message) {
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kMessages === 0) {
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kMessages = {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Error
1441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      cyclic_proto:                 ["Cyclic __proto__ value"],
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // TypeError
1461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_token:             ["Unexpected token ", "%0"],
1471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_token_number:      ["Unexpected number"],
1481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_token_string:      ["Unexpected string"],
1491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_token_identifier:  ["Unexpected identifier"],
1501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_strict_reserved:   ["Unexpected strict mode reserved word"],
1511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unexpected_eos:               ["Unexpected end of input"],
1521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      malformed_regexp:             ["Invalid regular expression: /", "%0", "/: ", "%1"],
1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unterminated_regexp:          ["Invalid regular expression: missing /"],
1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      regexp_flags:                 ["Cannot supply flags when constructing one RegExp from another"],
1551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
1561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_lhs_in_assignment:    ["Invalid left-hand side in assignment"],
1571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_lhs_in_for_in:        ["Invalid left-hand side in for-in"],
1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_lhs_in_postfix_op:    ["Invalid left-hand side expression in postfix operation"],
1591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_lhs_in_prefix_op:     ["Invalid left-hand side expression in prefix operation"],
1601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      multiple_defaults_in_switch:  ["More than one default clause in switch statement"],
1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      newline_after_throw:          ["Illegal newline after throw"],
1621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      redeclaration:                ["%0", " '", "%1", "' has already been declared"],
1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      no_catch_or_finally:          ["Missing catch or finally after try"],
1641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unknown_label:                ["Undefined label '", "%0", "'"],
1651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      uncaught_exception:           ["Uncaught ", "%0"],
1661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      stack_trace:                  ["Stack Trace:\n", "%0"],
1671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      called_non_callable:          ["%0", " is not a function"],
1681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      undefined_method:             ["Object ", "%1", " has no method '", "%0", "'"],
1691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      property_not_function:        ["Property '", "%0", "' of object ", "%1", " is not a function"],
1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      cannot_convert_to_primitive:  ["Cannot convert object to primitive value"],
1711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      not_constructor:              ["%0", " is not a constructor"],
1721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      not_defined:                  ["%0", " is not defined"],
1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      non_object_property_load:     ["Cannot read property '", "%0", "' of ", "%1"],
1741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      non_object_property_store:    ["Cannot set property '", "%0", "' of ", "%1"],
1751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      non_object_property_call:     ["Cannot call method '", "%0", "' of ", "%1"],
1761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      with_expression:              ["%0", " has no properties"],
1771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      illegal_invocation:           ["Illegal invocation"],
1781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      no_setter_in_callback:        ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
1791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      apply_non_function:           ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
1801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      apply_wrong_args:             ["Function.prototype.apply: Arguments list has wrong type"],
1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_in_operator_use:      ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
1821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"],
1831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      instanceof_nonobject_proto:   ["Function has non-object prototype '", "%0", "' in instanceof check"],
1841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      null_to_object:               ["Cannot convert null to object"],
1851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      reduce_no_initial:            ["Reduce of empty array with no initial value"],
1861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      getter_must_be_callable:      ["Getter must be a function: ", "%0"],
1871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      setter_must_be_callable:      ["Setter must be a function: ", "%0"],
1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      value_and_accessor:           ["Invalid property.  A property cannot both have accessors and be writable or have a value: ", "%0"],
1891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      proto_object_or_null:         ["Object prototype may only be an Object or null"],
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      property_desc_object:         ["Property description must be an object: ", "%0"],
1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      redefine_disallowed:          ["Cannot redefine property: ", "%0"],
1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      define_disallowed:            ["Cannot define property, object is not extensible: ", "%0"],
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // RangeError
1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_array_length:         ["Invalid array length"],
1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      stack_overflow:               ["Maximum call stack size exceeded"],
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // SyntaxError
1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unable_to_parse:              ["Parse error"],
1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      duplicate_regexp_flag:        ["Duplicate RegExp flag ", "%0"],
1991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_regexp:               ["Invalid RegExp pattern /", "%0", "/"],
2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      illegal_break:                ["Illegal break statement"],
2011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      illegal_continue:             ["Illegal continue statement"],
2021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      illegal_return:               ["Illegal return statement"],
2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      error_loading_debugger:       ["Error loading debugger"],
2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      no_input_to_regexp:           ["No input to ", "%0"],
2051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_json:                 ["String '", "%0", "' is not valid JSON"],
2061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      circular_structure:           ["Converting circular structure to JSON"],
2071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      obj_ctor_property_non_object: ["Object.", "%0", " called on non-object"],
2081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      array_indexof_not_defined:    ["Array.getIndexOf: Argument undefined"],
2091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      object_not_extensible:        ["Can't add property ", "%0", ", object is not extensible"],
2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      illegal_access:               ["Illegal access"],
2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      invalid_preparser_data:       ["Invalid preparser data for function ", "%0"],
2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_mode_with:             ["Strict mode code may not include a with statement"],
2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_catch_variable:        ["Catch variable may not be eval or arguments in strict mode"],
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      too_many_parameters:          ["Too many parameters in function definition"],
2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_param_name:            ["Parameter name eval or arguments is not allowed in strict mode"],
2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_param_dupe:            ["Strict mode function may not have duplicate parameter names"],
2171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_var_name:              ["Variable name may not be eval or arguments in strict mode"],
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_function_name:         ["Function name may not be eval or arguments in strict mode"],
2191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_octal_literal:         ["Octal literals are not allowed in strict mode."],
2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_duplicate_property:    ["Duplicate data property in object literal not allowed in strict mode"],
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      accessor_data_property:       ["Object literal may not have data and accessor property with the same name"],
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      accessor_get_set:             ["Object literal may not have multiple get/set accessors with the same name"],
2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_lhs_assignment:        ["Assignment to eval or arguments is not allowed in strict mode"],
2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_lhs_postfix:           ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_lhs_prefix:            ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      strict_reserved_word:         ["Use of future reserved word in strict mode"],
227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_delete:                ["Delete of an unqualified identifier in strict mode."],
228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_delete_property:       ["Cannot delete property '", "%0", "' of ", "%1"],
229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_const:                 ["Use of const in strict mode."],
230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_function:              ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_read_only_property:    ["Cannot assign to read only property '", "%0", "' of ", "%1"],
232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      strict_cannot_assign:         ["Cannot assign to read only '", "%0", "' in strict mode"],
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      strict_arguments_callee:      ["Cannot access property 'callee' of strict mode arguments"],
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      strict_arguments_caller:      ["Cannot access property 'caller' of strict mode arguments"],
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      strict_function_caller:       ["Cannot access property 'caller' of a strict mode function"],
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      strict_function_arguments:    ["Cannot access property 'arguments' of a strict mode function"],
23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      strict_caller:                ["Illegal access to a strict mode caller function."],
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    };
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var message_type = %MessageGetType(message);
2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var format = kMessages[message_type];
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!format) return "<unknown message " + message_type + ">";
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return FormatString(format, message);
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetLineNumber(message) {
2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var start_position = %MessageGetStartPosition(message);
2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (start_position == -1) return kNoLineNumberInfo;
2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var script = %MessageGetScript(message);
2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var location = script.locationFromPosition(start_position, true);
25225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (location == null) return kNoLineNumberInfo;
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return location.line + 1;
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the source code line containing the given source
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// position, or the empty string if the position is invalid.
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetSourceLine(message) {
2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var script = %MessageGetScript(message);
2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var start_position = %MessageGetStartPosition(message);
2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var location = script.locationFromPosition(start_position, true);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (location == null) return "";
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  location.restrict();
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return location.sourceText();
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeTypeError(type, args) {
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($TypeError, type, args);
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeRangeError(type, args) {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($RangeError, type, args);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeSyntaxError(type, args) {
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($SyntaxError, type, args);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeReferenceError(type, args) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($ReferenceError, type, args);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeEvalError(type, args) {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($EvalError, type, args);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction MakeError(type, args) {
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MakeGenericError($Error, type, args);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Find a line number given a specific source position.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} position The source position.
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {number} 0 if input too small, -1 if input too large,
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       else the line number.
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.lineFromPosition = function(position) {
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var lower = 0;
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var upper = this.lineCount() - 1;
307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var line_ends = this.line_ends;
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We'll never find invalid positions so bail right away.
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (position > line_ends[upper]) {
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return -1;
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This means we don't have to safe-guard indexing line_ends[i - 1].
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (position <= line_ends[0]) {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 0;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Binary search to find line # from position range.
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (upper >= 1) {
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var i = (lower + upper) >> 1;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (position > line_ends[i]) {
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      lower = i + 1;
325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else if (position <= line_ends[i - 1]) {
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      upper = i - 1;
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return i;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Get information on a specific source position.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} position The source position
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {boolean} include_resource_offset Set to true to have the resource
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     offset added to the location
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {SourceLocation}
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     If line is negative or not in the source null is returned.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.locationFromPosition = function (position,
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  include_resource_offset) {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = this.lineFromPosition(position);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (line == -1) return null;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determine start, end and column.
349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var line_ends = this.line_ends;
350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var start = line == 0 ? 0 : line_ends[line - 1] + 1;
351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var end = line_ends[line];
3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') end--;
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var column = position - start;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust according to the offset within the resource.
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (include_resource_offset) {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += this.line_offset;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (line == this.line_offset) {
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      column += this.column_offset;
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return new SourceLocation(this, position, line, column, start, end);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Get information on a specific source line and column possibly offset by a
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * fixed source position. This function is used to find a source position from
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * a line and column position. The fixed source position offset is typically
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * used to find a source position in a function based on a line and column in
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * the source for the function alone. The offset passed will then be the
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * start position of the source for the function within the full script source.
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_line The line within the source. Default value is 0
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_column The column in within the line. Default value is 0
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_offset_position The offset from the begining of the
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     source from where the line and column calculation starts. Default value is 0
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {SourceLocation}
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     If line is negative or not in the source null is returned.
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_position) {
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default is the first line in the script. Lines in the script is relative
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the offset within the resource.
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = 0;
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!IS_UNDEFINED(opt_line)) {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line = opt_line - this.line_offset;
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default is first column. If on the first line add the offset within the
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // resource.
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var column = opt_column || 0;
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (line == 0) {
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    column -= this.column_offset
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var offset_position = opt_offset_position || 0;
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (line < 0 || column < 0 || offset_position < 0) return null;
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (line == 0) {
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return this.locationFromPosition(offset_position + column, false);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Find the line where the offset position is located.
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var offset_line = this.lineFromPosition(offset_position);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (offset_line == -1 || offset_line + line >= this.lineCount()) {
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return null;
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return this.locationFromPosition(this.line_ends[offset_line + line - 1] + 1 + column);  // line > 0 here.
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Get a slice of source code from the script. The boundaries for the slice is
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * specified in lines.
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_from_line The first line (zero bound) in the slice.
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     Default is 0
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_to_column The last line (zero bound) in the slice (non
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     inclusive). Default is the number of lines in the script
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {SourceSlice} The source slice or null of the parameters where
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     invalid
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset : opt_from_line;
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount() : opt_to_line
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust according to the offset within the resource.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  from_line -= this.line_offset;
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  to_line -= this.line_offset;
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (from_line < 0) from_line = 0;
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (to_line > this.lineCount()) to_line = this.lineCount();
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check parameters.
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (from_line >= this.lineCount() ||
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      to_line < 0 ||
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      from_line > to_line) {
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return null;
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var line_ends = this.line_ends;
441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return a source slice with line numbers re-adjusted to the resource.
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return new SourceSlice(this, from_line + this.line_offset, to_line + this.line_offset,
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         from_position, to_position);
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.sourceLine = function (opt_line) {
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default is the first line in the script. Lines in the script are relative
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the offset within the resource.
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = 0;
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!IS_UNDEFINED(opt_line)) {
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line = opt_line - this.line_offset;
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check parameter.
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (line < 0 || this.lineCount() <= line) {
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return null;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the source line.
464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var line_ends = this.line_ends;
465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var start = line == 0 ? 0 : line_ends[line - 1] + 1;
466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var end = line_ends[line];
4671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return %_CallFunction(this.source, start, end, StringSubstring);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Returns the number of source lines.
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {number}
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     Number of source lines.
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScript.prototype.lineCount = function() {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return number of source lines.
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.line_ends.length;
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * Returns the name of script if available, contents of sourceURL comment
484f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch * otherwise. See
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * for details on using //@ sourceURL comment to identify scritps that don't
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * have name.
488f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch *
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * @return {?string} script name if present, value for //@ sourceURL comment
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block * otherwise.
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block */
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockScript.prototype.nameOrSourceURL = function() {
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (this.name)
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this.name;
495f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // TODO(608): the spaces in a regexp below had to be escaped as \040
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // because this file is being processed by js2c whose handling of spaces
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in regexps is broken. Also, ['"] are excluded from allowed URLs to
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // avoid matches against sources that invoke evals with sourceURL.
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // A better solution would be to detect these special comments in
50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // the scanner/parser.
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  var source = ToString(this.source);
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  var sourceUrlPos = %StringIndexOf(source, "sourceURL=", 0);
50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (sourceUrlPos > 4) {
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    var sourceUrlPattern =
50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        /\/\/@[\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Don't reuse lastMatchInfo here, so we create a new array with room
50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // for four captures (array with length one longer than the index
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the fourth capture, where the numbering is zero-based).
50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    var matchInfo = new InternalArray(CAPTURE(3) + 1);
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    var match =
51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        %_RegExpExec(sourceUrlPattern, source, sourceUrlPos - 4, matchInfo);
51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (match) {
51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return SubString(source, matchInfo[CAPTURE(2)], matchInfo[CAPTURE(3)]);
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return this.name;
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block/**
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Class for source location. A source location is a position within some
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * source with the following properties:
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   script   : script object for the source
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   line     : source line number
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   column   : source column within the line
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   position : position within the source
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   start    : position of start of source context (inclusive)
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   end      : position of end of source context (not inclusive)
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Source text for the source context is the character interval [start, end[. In
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * most cases end will point to a newline character. It might point just past
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * the final position of the source if the last source line does not end with a
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * newline character.
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {Script} script The Script object for which this is a location
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} position Source position for the location
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} line The line number for the location
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} column The column within the line for the location
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} start Source position for start of source context
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} end Source position for end of source context
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @constructor
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SourceLocation(script, position, line, column, start, end) {
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.script = script;
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.position = position;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.line = line;
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.column = column;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.start = start;
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.end = end;
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst kLineLengthLimit = 78;
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Restrict source location start and end positions to make the source slice
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * no more that a certain number of characters wide.
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_limit The with limit of the source text with a default
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     of 78
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} opt_before The number of characters to prefer before the
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     position with a default value of 10 less that the limit
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSourceLocation.prototype.restrict = function (opt_limit, opt_before) {
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the actual limit to use.
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var limit;
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var before;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!IS_UNDEFINED(opt_limit)) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    limit = opt_limit;
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    limit = kLineLengthLimit;
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!IS_UNDEFINED(opt_before)) {
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    before = opt_before;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If no before is specified center for small limits and perfer more source
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // before the the position that after for longer limits.
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (limit <= 20) {
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      before = $floor(limit / 2);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      before = limit - 10;
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (before >= limit) {
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    before = limit - 1;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the [start, end[ interval is too big we restrict
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it in one or both ends. We make sure to always produce
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // restricted intervals of maximum allowed size.
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.end - this.start > limit) {
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var start_limit = this.position - before;
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var end_limit = this.position + limit - before;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (this.start < start_limit && end_limit < this.end) {
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.start = start_limit;
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.end = end_limit;
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (this.start < start_limit) {
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.start = this.end - limit;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this.end = this.start + limit;
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Get the source text for a SourceLocation
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {String}
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     Source text for this location.
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSourceLocation.prototype.sourceText = function () {
6091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return %_CallFunction(this.script.source, this.start, this.end, StringSubstring);
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Class for a source slice. A source slice is a part of a script source with
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * the following properties:
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   script        : script object for the source
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   from_line     : line number for the first line in the slice
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   to_line       : source line number for the last line in the slice
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   from_position : position of the first character in the slice
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *   to_position   : position of the last character in the slice
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The to_line and to_position are not included in the slice, that is the lines
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * in the slice are [from_line, to_line[. Likewise the characters in the slice
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * are [from_position, to_position[.
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {Script} script The Script object for the source slice
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} from_line
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} to_line
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} from_position
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @param {number} to_position
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @constructor
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SourceSlice(script, from_line, to_line, from_position, to_position) {
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.script = script;
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.from_line = from_line;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.to_line = to_line;
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.from_position = from_position;
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.to_position = to_position;
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Get the source text for a SourceSlice
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @return {String} Source text for this slice. The last line will include
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *     the line terminating characters (if any)
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSourceSlice.prototype.sourceText = function () {
6461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return %_CallFunction(this.script.source,
6471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        this.from_position,
6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        this.to_position,
6491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        StringSubstring);
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the offset of the given position within the containing
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// line.
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetPositionInLine(message) {
6561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var script = %MessageGetScript(message);
6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var start_position = %MessageGetStartPosition(message);
6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var location = script.locationFromPosition(start_position, false);
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (location == null) return -1;
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  location.restrict();
6611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return start_position - location.start;
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction GetStackTraceLine(recv, fun, pos, isGlobal) {
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return FormatSourcePosition(new CallSite(recv, fun, pos));
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Error implementation
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defines accessors for a property that is calculated the first time
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the property is read.
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction DefineOneShotAccessor(obj, name, fun) {
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that the accessors consistently operate on 'obj', not 'this'.
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since the object may occur in someone else's prototype chain we
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // can't rely on 'this' being the same as 'obj'.
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var hasBeenSet = false;
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var value;
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj.__defineGetter__(name, function () {
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (hasBeenSet) {
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return value;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    hasBeenSet = true;
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = fun(obj);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return value;
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  obj.__defineSetter__(name, function (v) {
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    hasBeenSet = true;
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = v;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction CallSite(receiver, fun, pos) {
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.receiver = receiver;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.fun = fun;
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.pos = pos;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getThis = function () {
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.receiver;
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getTypeName = function () {
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var constructor = this.receiver.constructor;
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!constructor)
7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return %_CallFunction(this.receiver, ObjectToString);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var constructorName = constructor.name;
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!constructorName)
7101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return %_CallFunction(this.receiver, ObjectToString);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return constructorName;
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.isToplevel = function () {
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.receiver == null)
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IS_GLOBAL(this.receiver);
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.isEval = function () {
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
7223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return script && script.compilation_type == COMPILATION_TYPE_EVAL;
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getEvalOrigin = function () {
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return FormatEvalOrigin(script);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7300d5e116f6aee03185f237311a943491bb079a768Kristian MonsenCallSite.prototype.getScriptNameOrSourceURL = function () {
7310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  var script = %FunctionGetScript(this.fun);
7320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return script ? script.nameOrSourceURL() : null;
7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
7340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getFunction = function () {
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.fun;
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getFunctionName = function () {
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // See if the function knows its own name
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var name = this.fun.name;
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name) {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return name;
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return %FunctionGetInferredName(this.fun);
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Maybe this is an evaluation?
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
7493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if (script && script.compilation_type == COMPILATION_TYPE_EVAL)
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return "eval";
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return null;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getMethodName = function () {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // See if we can find a unique property on the receiver that holds
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // this function.
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var ownName = this.fun.name;
758756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (ownName && this.receiver &&
7591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      (%_CallFunction(this.receiver, ownName, ObjectLookupGetter) === this.fun ||
7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block       %_CallFunction(this.receiver, ownName, ObjectLookupSetter) === this.fun ||
761756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick       this.receiver[ownName] === this.fun)) {
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // To handle DontEnum properties we guess that the method has
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the same name as the function.
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ownName;
765756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var name = null;
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var prop in this.receiver) {
768756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (this.receiver.__lookupGetter__(prop) === this.fun ||
769756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        this.receiver.__lookupSetter__(prop) === this.fun ||
770756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        (!this.receiver.__lookupGetter__(prop) && this.receiver[prop] === this.fun)) {
771756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // If we find more than one match bail out to avoid confusion.
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (name)
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return null;
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      name = prop;
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name)
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return name;
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return null;
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getFileName = function () {
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return script ? script.name : null;
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getLineNumber = function () {
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.pos == -1)
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return null;
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var location = null;
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (script) {
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    location = script.locationFromPosition(this.pos, true);
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return location ? location.line + 1 : null;
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getColumnNumber = function () {
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this.pos == -1)
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return null;
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var location = null;
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (script) {
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    location = script.locationFromPosition(this.pos, true);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return location ? location.column + 1: null;
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.isNative = function () {
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var script = %FunctionGetScript(this.fun);
8113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return script ? (script.type == TYPE_NATIVE) : false;
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.getPosition = function () {
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.pos;
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCallSite.prototype.isConstructor = function () {
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var constructor = this.receiver ? this.receiver.constructor : null;
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!constructor)
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return this.fun === constructor;
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockfunction FormatEvalOrigin(script) {
8260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  var sourceURL = script.nameOrSourceURL();
8270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (sourceURL)
8280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return sourceURL;
8290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  var eval_origin = "eval at ";
831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (script.eval_from_function_name) {
832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    eval_origin += script.eval_from_function_name;
833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    eval_origin +=  "<anonymous>";
835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  var eval_from_script = script.eval_from_script;
838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (eval_from_script) {
8393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      // eval script originated from another eval.
8410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
8430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // eval script originated from "real" source.
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (eval_from_script.name) {
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        eval_origin += " (" + eval_from_script.name;
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        var location = eval_from_script.locationFromPosition(script.eval_from_script_position, true);
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (location) {
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          eval_origin += ":" + (location.line + 1);
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          eval_origin += ":" + (location.column + 1);
850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        eval_origin += ")"
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        eval_origin += " (unknown source)";
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return eval_origin;
859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction FormatSourcePosition(frame) {
8620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  var fileName;
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var fileLocation = "";
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (frame.isNative()) {
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fileLocation = "native";
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (frame.isEval()) {
8670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    fileName = frame.getScriptNameOrSourceURL();
8680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!fileName)
8690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      fileLocation = frame.getEvalOrigin();
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
8710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    fileName = frame.getFileName();
8720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
8730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (fileName) {
8750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    fileLocation += fileName;
8760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    var lineNumber = frame.getLineNumber();
8770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (lineNumber != null) {
8780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      fileLocation += ":" + lineNumber;
8790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      var columnNumber = frame.getColumnNumber();
8800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (columnNumber) {
8810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        fileLocation += ":" + columnNumber;
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!fileLocation) {
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fileLocation = "unknown source";
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var line = "";
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var functionName = frame.getFunction().name;
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var addPrefix = true;
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var isConstructor = frame.isConstructor();
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var isMethodCall = !(frame.isToplevel() || isConstructor);
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (isMethodCall) {
8959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    var methodName = frame.getMethodName();
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += frame.getTypeName() + ".";
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (functionName) {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      line += functionName;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (methodName && (methodName != functionName)) {
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        line += " [as " + methodName + "]";
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      line += methodName || "<anonymous>";
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (isConstructor) {
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += "new " + (functionName || "<anonymous>");
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (functionName) {
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += functionName;
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += fileLocation;
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    addPrefix = false;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (addPrefix) {
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    line += " (" + fileLocation + ")";
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return line;
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction FormatStackTrace(error, frames) {
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var lines = [];
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  try {
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    lines.push(error.toString());
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } catch (e) {
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    try {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      lines.push("<error: " + e + ">");
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } catch (ee) {
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      lines.push("<error>");
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (var i = 0; i < frames.length; i++) {
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var frame = frames[i];
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var line;
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    try {
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      line = FormatSourcePosition(frame);
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } catch (e) {
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      try {
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        line = "<error: " + e + ">";
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } catch (ee) {
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Any code that reaches this point is seriously nasty!
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        line = "<error>";
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    lines.push("    at " + line);
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return lines.join("\n");
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction FormatRawStackTrace(error, raw_stack) {
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var frames = [ ];
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (var i = 0; i < raw_stack.length; i += 4) {
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var recv = raw_stack[i];
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var fun = raw_stack[i + 1];
953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var code = raw_stack[i + 2];
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var pc = raw_stack[i + 3];
955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var pos = %FunctionGetPositionForOffset(code, pc);
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    frames.push(new CallSite(recv, fun, pos));
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IS_FUNCTION($Error.prepareStackTrace)) {
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return $Error.prepareStackTrace(error, frames);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return FormatStackTrace(error, frames);
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction DefineError(f) {
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the error function in both the global object
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and the runtime object. The function is fetched
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from the runtime object when throwing errors from
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // within the runtime system to avoid strange side
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // effects when overwriting the error functions from
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // user code.
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var name = f.name;
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %SetProperty(global, name, f, DONT_ENUM);
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this['$' + name] = f;
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Configure the error function.
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (name == 'Error') {
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The prototype of the Error object must itself be an error.
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // However, it can't be an instance of the Error object because
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // it hasn't been properly configured yet.  Instead we create a
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // special not-a-true-error-but-close-enough object.
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    function ErrorPrototype() {}
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %FunctionSetPrototype(f, new ErrorPrototype());
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %FunctionSetPrototype(f, new $Error());
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %FunctionSetInstanceClassName(f, 'Error');
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
990b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // The name property on the prototype of error objects is not
991b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // specified as being read-one and dont-delete. However, allowing
992b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // overwriting allows leaks of error objects between script blocks
993b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // in the same context in a browser setting. Therefore we fix the
994b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // name.
995b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  %SetProperty(f.prototype, "name", name, READ_ONLY | DONT_DELETE);
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %SetCode(f, function(m) {
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (%_IsConstructCall()) {
998b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // Define all the expected properties directly on the error
999b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // object. This avoids going through getters and setters defined
1000b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // on prototype objects.
1001b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      %IgnoreAttributesAndSetProperty(this, 'stack', void 0);
1002b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      %IgnoreAttributesAndSetProperty(this, 'arguments', void 0);
1003b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      %IgnoreAttributesAndSetProperty(this, 'type', void 0);
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (m === kAddMessageAccessorsMarker) {
1005b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        // DefineOneShotAccessor always inserts a message property and
1006b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        // ignores setters.
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        DefineOneShotAccessor(this, 'message', function (obj) {
10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        });
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (!IS_UNDEFINED(m)) {
1011b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        %IgnoreAttributesAndSetProperty(this, 'message', ToString(m));
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      captureStackTrace(this, f);
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return new f(m);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction captureStackTrace(obj, cons_opt) {
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var stackTraceLimit = $Error.stackTraceLimit;
10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (stackTraceLimit < 0 || stackTraceLimit > 10000)
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stackTraceLimit = 10000;
10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  var raw_stack = %CollectStackTrace(cons_opt
10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                     ? cons_opt
10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                     : captureStackTrace, stackTraceLimit);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DefineOneShotAccessor(obj, 'stack', function (obj) {
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return FormatRawStackTrace(obj, raw_stack);
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  });
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block$Math.__proto__ = global.Object.prototype;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function Error() { });
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function TypeError() { });
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function RangeError() { });
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function SyntaxError() { });
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function ReferenceError() { });
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function EvalError() { });
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDefineError(function URIError() { });
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block$Error.captureStackTrace = captureStackTrace;
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Setup extra properties of the Error.prototype object.
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block$Error.prototype.message = '';
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Global list of error objects visited during errorToString. This is
10491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// used to detect cycles in error toString formatting.
10501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvar visited_errors = new $Array();
10511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvar cyclic_error_marker = new $Object();
10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockfunction errorToStringDetectCycle() {
10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker;
10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  try {
10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    var type = this.type;
10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) {
10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      var formatted = FormatMessage(%NewMessageObject(type, this.arguments));
10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return this.name + ": " + formatted;
10601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
10611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    var message = %_CallFunction(this, "message", ObjectHasOwnProperty)
10621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ? (": " + this.message)
10631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        : "";
10641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return this.name + message;
10651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } finally {
10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    visited_errors.length = visited_errors.length - 1;
10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
10691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochfunction errorToString() {
10711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // This helper function is needed because access to properties on
10721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the builtins object do not work inside of a catch clause.
10731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  function isCyclicErrorMarker(o) { return o === cyclic_error_marker; }
10741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  try {
10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return %_CallFunction(this, errorToStringDetectCycle);
10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } catch(e) {
10781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // If this error message was encountered already return the empty
10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // string for it instead of recursively formatting it.
10801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (isCyclicErrorMarker(e)) return '';
10811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    else throw e;
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1083b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1084b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochInstallFunctions($Error.prototype, DONT_ENUM, ['toString', errorToString]);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Boilerplate for exceptions for stack overflows. Used from
108944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Isolate::StackOverflow().
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []);
1091