2008-09-09 20:08:45 +00:00
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2008-07-03 15:10:15 +00:00
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -------------------------------------------------------------------
2010-03-23 11:40:38 +00:00
//
// Matches Script::Type from objects.h
var TYPE _NATIVE = 0 ;
var TYPE _EXTENSION = 1 ;
var TYPE _NORMAL = 2 ;
// Matches Script::CompilationType from objects.h
var COMPILATION _TYPE _HOST = 0 ;
var COMPILATION _TYPE _EVAL = 1 ;
var COMPILATION _TYPE _JSON = 2 ;
2008-07-03 15:10:15 +00:00
2010-05-06 07:32:44 +00:00
// Matches Messages::kNoLineNumberInfo from v8.h
var kNoLineNumberInfo = 0 ;
2009-09-23 12:32:24 +00:00
// If this object gets passed to an error constructor the error will
// get an accessor for .message that constructs a descriptive error
// message on access.
var kAddMessageAccessorsMarker = { } ;
2009-08-13 07:36:28 +00:00
var kMessages = 0 ;
2008-07-03 15:10:15 +00:00
2011-02-03 14:02:13 +00:00
var kReplacementMarkers = [ "%0" , "%1" , "%2" , "%3" ] ;
2008-07-03 15:10:15 +00:00
2011-02-02 13:31:52 +00:00
function FormatString ( format , message ) {
var args = % MessageGetArguments ( message ) ;
2011-02-01 12:31:16 +00:00
var result = "" ;
var arg _num = 0 ;
for ( var i = 0 ; i < format . length ; i ++ ) {
var str = format [ i ] ;
for ( arg _num = 0 ; arg _num < kReplacementMarkers . length ; arg _num ++ ) {
if ( format [ i ] !== kReplacementMarkers [ arg _num ] ) continue ;
try {
str = ToDetailString ( args [ arg _num ] ) ;
} catch ( e ) {
str = "#<error>" ;
}
2011-01-26 15:16:13 +00:00
}
2011-02-01 12:31:16 +00:00
result += str ;
2008-07-03 15:10:15 +00:00
}
return result ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
2011-01-25 08:48:59 +00:00
// To check if something is a native error we need to check the
// concrete native error types. It is not enough to check "obj
// instanceof $Error" because user code can replace
// NativeError.prototype.__proto__. User code cannot replace
// NativeError.prototype though and therefore this is a safe test.
function IsNativeErrorObject ( obj ) {
return ( obj instanceof $Error ) ||
( obj instanceof $EvalError ) ||
( obj instanceof $RangeError ) ||
( obj instanceof $ReferenceError ) ||
( obj instanceof $SyntaxError ) ||
( obj instanceof $TypeError ) ||
( obj instanceof $URIError ) ;
}
2011-01-24 07:59:40 +00:00
// When formatting internally created error messages, do not
// invoke overwritten error toString methods but explicitly use
// the error to string method. This is to avoid leaking error
// objects between script tags in a browser setting.
function ToStringCheckErrorObject ( obj ) {
2011-01-25 08:48:59 +00:00
if ( IsNativeErrorObject ( obj ) ) {
2011-01-24 07:59:40 +00:00
return % _CallFunction ( obj , errorToString ) ;
} else {
return ToString ( obj ) ;
}
}
2008-07-03 15:10:15 +00:00
function ToDetailString ( obj ) {
if ( obj != null && IS _OBJECT ( obj ) && obj . toString === $Object . prototype . toString ) {
var constructor = obj . constructor ;
2011-01-24 07:59:40 +00:00
if ( ! constructor ) return ToStringCheckErrorObject ( obj ) ;
2008-07-03 15:10:15 +00:00
var constructorName = constructor . name ;
2011-01-26 15:16:13 +00:00
if ( ! constructorName || ! IS _STRING ( constructorName ) ) {
return ToStringCheckErrorObject ( obj ) ;
}
2011-01-28 10:33:10 +00:00
return "#<" + constructorName + ">" ;
2008-07-03 15:10:15 +00:00
} else {
2011-01-24 07:59:40 +00:00
return ToStringCheckErrorObject ( obj ) ;
2008-07-03 15:10:15 +00:00
}
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeGenericError ( constructor , type , args ) {
2009-06-25 10:27:36 +00:00
if ( IS _UNDEFINED ( args ) ) {
2008-09-10 11:41:48 +00:00
args = [ ] ;
2008-07-03 15:10:15 +00:00
}
2009-03-09 12:50:32 +00:00
var e = new constructor ( kAddMessageAccessorsMarker ) ;
2008-07-03 15:10:15 +00:00
e . type = type ;
e . arguments = args ;
return e ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
/ * *
* Setup the Script function and constructor .
* /
% FunctionSetInstanceClassName ( Script , 'Script' ) ;
2008-10-03 12:14:29 +00:00
% SetProperty ( Script . prototype , 'constructor' , Script , DONT _ENUM ) ;
2008-07-03 15:10:15 +00:00
% SetCode ( Script , function ( x ) {
// Script objects can only be created by the VM.
throw new $Error ( "Not supported" ) ;
} ) ;
// Helper functions; called from the runtime system.
function FormatMessage ( message ) {
2009-08-13 07:36:28 +00:00
if ( kMessages === 0 ) {
kMessages = {
// Error
2011-02-01 12:31:16 +00:00
cyclic _proto : [ "Cyclic __proto__ value" ] ,
2011-05-03 05:40:47 +00:00
code _gen _from _strings : [ "Code generation from strings disallowed for this context" ] ,
2009-08-13 07:36:28 +00:00
// TypeError
2011-02-01 12:31:16 +00:00
unexpected _token : [ "Unexpected token " , "%0" ] ,
unexpected _token _number : [ "Unexpected number" ] ,
unexpected _token _string : [ "Unexpected string" ] ,
unexpected _token _identifier : [ "Unexpected identifier" ] ,
2011-02-04 18:36:37 +00:00
unexpected _strict _reserved : [ "Unexpected strict mode reserved word" ] ,
2011-02-01 12:31:16 +00:00
unexpected _eos : [ "Unexpected end of input" ] ,
malformed _regexp : [ "Invalid regular expression: /" , "%0" , "/: " , "%1" ] ,
unterminated _regexp : [ "Invalid regular expression: missing /" ] ,
regexp _flags : [ "Cannot supply flags when constructing one RegExp from another" ] ,
incompatible _method _receiver : [ "Method " , "%0" , " called on incompatible receiver " , "%1" ] ,
invalid _lhs _in _assignment : [ "Invalid left-hand side in assignment" ] ,
invalid _lhs _in _for _in : [ "Invalid left-hand side in for-in" ] ,
invalid _lhs _in _postfix _op : [ "Invalid left-hand side expression in postfix operation" ] ,
invalid _lhs _in _prefix _op : [ "Invalid left-hand side expression in prefix operation" ] ,
multiple _defaults _in _switch : [ "More than one default clause in switch statement" ] ,
newline _after _throw : [ "Illegal newline after throw" ] ,
redeclaration : [ "%0" , " '" , "%1" , "' has already been declared" ] ,
no _catch _or _finally : [ "Missing catch or finally after try" ] ,
unknown _label : [ "Undefined label '" , "%0" , "'" ] ,
uncaught _exception : [ "Uncaught " , "%0" ] ,
stack _trace : [ "Stack Trace:\n" , "%0" ] ,
called _non _callable : [ "%0" , " is not a function" ] ,
undefined _method : [ "Object " , "%1" , " has no method '" , "%0" , "'" ] ,
property _not _function : [ "Property '" , "%0" , "' of object " , "%1" , " is not a function" ] ,
cannot _convert _to _primitive : [ "Cannot convert object to primitive value" ] ,
not _constructor : [ "%0" , " is not a constructor" ] ,
not _defined : [ "%0" , " is not defined" ] ,
non _object _property _load : [ "Cannot read property '" , "%0" , "' of " , "%1" ] ,
non _object _property _store : [ "Cannot set property '" , "%0" , "' of " , "%1" ] ,
non _object _property _call : [ "Cannot call method '" , "%0" , "' of " , "%1" ] ,
with _expression : [ "%0" , " has no properties" ] ,
illegal _invocation : [ "Illegal invocation" ] ,
no _setter _in _callback : [ "Cannot set property " , "%0" , " of " , "%1" , " which has only a getter" ] ,
apply _non _function : [ "Function.prototype.apply was called on " , "%0" , ", which is a " , "%1" , " and not a function" ] ,
apply _wrong _args : [ "Function.prototype.apply: Arguments list has wrong type" ] ,
invalid _in _operator _use : [ "Cannot use 'in' operator to search for '" , "%0" , "' in " , "%1" ] ,
instanceof _function _expected : [ "Expecting a function in instanceof check, but got " , "%0" ] ,
instanceof _nonobject _proto : [ "Function has non-object prototype '" , "%0" , "' in instanceof check" ] ,
null _to _object : [ "Cannot convert null to object" ] ,
reduce _no _initial : [ "Reduce of empty array with no initial value" ] ,
getter _must _be _callable : [ "Getter must be a function: " , "%0" ] ,
setter _must _be _callable : [ "Setter must be a function: " , "%0" ] ,
value _and _accessor : [ "Invalid property. A property cannot both have accessors and be writable or have a value: " , "%0" ] ,
proto _object _or _null : [ "Object prototype may only be an Object or null" ] ,
property _desc _object : [ "Property description must be an object: " , "%0" ] ,
redefine _disallowed : [ "Cannot redefine property: " , "%0" ] ,
2011-06-14 11:28:14 +00:00
define _disallowed : [ "Cannot define property:" , "%0" , ", object is not extensible." ] ,
2011-04-06 16:22:06 +00:00
non _extensible _proto : [ "%0" , " is not extensible" ] ,
2011-06-03 10:15:49 +00:00
handler _non _object : [ "Proxy." , "%0" , " called with non-object as handler" ] ,
2011-05-16 16:33:58 +00:00
handler _trap _missing : [ "Proxy handler " , "%0" , " has no '" , "%1" , "' trap" ] ,
2011-06-03 10:15:49 +00:00
proxy _prop _not _configurable : [ "Trap " , "%1" , " of proxy handler " , "%0" , " returned non-configurable descriptor for property " , "%2" ] ,
proxy _non _object _prop _names : [ "Trap " , "%1" , " returned non-object " , "%0" ] ,
proxy _repeated _prop _name : [ "Trap " , "%1" , " returned repeated property name " , "%2" ] ,
2009-08-13 07:36:28 +00:00
// RangeError
2011-02-01 12:31:16 +00:00
invalid _array _length : [ "Invalid array length" ] ,
stack _overflow : [ "Maximum call stack size exceeded" ] ,
2009-08-13 07:36:28 +00:00
// SyntaxError
2011-02-01 12:31:16 +00:00
unable _to _parse : [ "Parse error" ] ,
duplicate _regexp _flag : [ "Duplicate RegExp flag " , "%0" ] ,
invalid _regexp : [ "Invalid RegExp pattern /" , "%0" , "/" ] ,
illegal _break : [ "Illegal break statement" ] ,
illegal _continue : [ "Illegal continue statement" ] ,
illegal _return : [ "Illegal return statement" ] ,
error _loading _debugger : [ "Error loading debugger" ] ,
no _input _to _regexp : [ "No input to " , "%0" ] ,
invalid _json : [ "String '" , "%0" , "' is not valid JSON" ] ,
circular _structure : [ "Converting circular structure to JSON" ] ,
obj _ctor _property _non _object : [ "Object." , "%0" , " called on non-object" ] ,
2011-05-05 05:21:30 +00:00
called _on _null _or _undefined : [ "%0" , " called on null or undefined" ] ,
2011-02-01 12:31:16 +00:00
array _indexof _not _defined : [ "Array.getIndexOf: Argument undefined" ] ,
object _not _extensible : [ "Can't add property " , "%0" , ", object is not extensible" ] ,
illegal _access : [ "Illegal access" ] ,
invalid _preparser _data : [ "Invalid preparser data for function " , "%0" ] ,
strict _mode _with : [ "Strict mode code may not include a with statement" ] ,
strict _catch _variable : [ "Catch variable may not be eval or arguments in strict mode" ] ,
2011-06-07 08:15:47 +00:00
too _many _arguments : [ "Too many arguments in function call (only 32766 allowed)" ] ,
2011-05-16 08:27:52 +00:00
too _many _parameters : [ "Too many parameters in function definition (only 32766 allowed)" ] ,
too _many _variables : [ "Too many variables declared (only 32767 allowed)" ] ,
2011-02-01 12:31:16 +00:00
strict _param _name : [ "Parameter name eval or arguments is not allowed in strict mode" ] ,
strict _param _dupe : [ "Strict mode function may not have duplicate parameter names" ] ,
strict _var _name : [ "Variable name may not be eval or arguments in strict mode" ] ,
strict _function _name : [ "Function name may not be eval or arguments in strict mode" ] ,
strict _octal _literal : [ "Octal literals are not allowed in strict mode." ] ,
strict _duplicate _property : [ "Duplicate data property in object literal not allowed in strict mode" ] ,
accessor _data _property : [ "Object literal may not have data and accessor property with the same name" ] ,
accessor _get _set : [ "Object literal may not have multiple get/set accessors with the same name" ] ,
2011-02-01 16:08:44 +00:00
strict _lhs _assignment : [ "Assignment to eval or arguments is not allowed in strict mode" ] ,
2011-02-01 12:31:16 +00:00
strict _lhs _postfix : [ "Postfix increment/decrement may not have eval or arguments operand in strict mode" ] ,
strict _lhs _prefix : [ "Prefix increment/decrement may not have eval or arguments operand in strict mode" ] ,
2011-02-04 18:36:37 +00:00
strict _reserved _word : [ "Use of future reserved word in strict mode" ] ,
2011-02-14 18:44:26 +00:00
strict _delete : [ "Delete of an unqualified identifier in strict mode." ] ,
2011-02-14 23:41:47 +00:00
strict _delete _property : [ "Cannot delete property '" , "%0" , "' of " , "%1" ] ,
2011-02-28 18:38:17 +00:00
strict _const : [ "Use of const in strict mode." ] ,
2011-02-28 19:07:02 +00:00
strict _function : [ "In strict mode code, functions can only be declared at top level or immediately within another function." ] ,
2011-03-02 04:53:43 +00:00
strict _read _only _property : [ "Cannot assign to read only property '" , "%0" , "' of " , "%1" ] ,
strict _cannot _assign : [ "Cannot assign to read only '" , "%0" , "' in strict mode" ] ,
2011-05-24 11:07:06 +00:00
strict _poison _pill : [ "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them" ] ,
2011-03-23 03:45:48 +00:00
strict _caller : [ "Illegal access to a strict mode caller function." ] ,
2009-08-13 07:36:28 +00:00
} ;
}
2011-02-02 13:31:52 +00:00
var message _type = % MessageGetType ( message ) ;
var format = kMessages [ message _type ] ;
if ( ! format ) return "<unknown message " + message _type + ">" ;
return FormatString ( format , message ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function GetLineNumber ( message ) {
2011-02-02 13:31:52 +00:00
var start _position = % MessageGetStartPosition ( message ) ;
if ( start _position == - 1 ) return kNoLineNumberInfo ;
var script = % MessageGetScript ( message ) ;
var location = script . locationFromPosition ( start _position , true ) ;
2010-05-06 07:32:44 +00:00
if ( location == null ) return kNoLineNumberInfo ;
2008-07-03 15:10:15 +00:00
return location . line + 1 ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
// Returns the source code line containing the given source
// position, or the empty string if the position is invalid.
function GetSourceLine ( message ) {
2011-02-02 13:31:52 +00:00
var script = % MessageGetScript ( message ) ;
var start _position = % MessageGetStartPosition ( message ) ;
var location = script . locationFromPosition ( start _position , true ) ;
2008-07-03 15:10:15 +00:00
if ( location == null ) return "" ;
location . restrict ( ) ;
return location . sourceText ( ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeTypeError ( type , args ) {
return MakeGenericError ( $TypeError , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeRangeError ( type , args ) {
return MakeGenericError ( $RangeError , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeSyntaxError ( type , args ) {
return MakeGenericError ( $SyntaxError , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeReferenceError ( type , args ) {
return MakeGenericError ( $ReferenceError , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeEvalError ( type , args ) {
return MakeGenericError ( $EvalError , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function MakeError ( type , args ) {
return MakeGenericError ( $Error , type , args ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
2009-06-09 07:03:21 +00:00
/ * *
* Find a line number given a specific source position .
* @ param { number } position The source position .
* @ return { number } 0 if input too small , - 1 if input too large ,
else the line number .
* /
Script . prototype . lineFromPosition = function ( position ) {
var lower = 0 ;
var upper = this . lineCount ( ) - 1 ;
2009-11-27 14:10:48 +00:00
var line _ends = this . line _ends ;
2009-06-09 07:03:21 +00:00
// We'll never find invalid positions so bail right away.
2009-11-27 14:10:48 +00:00
if ( position > line _ends [ upper ] ) {
2009-06-09 07:03:21 +00:00
return - 1 ;
}
// This means we don't have to safe-guard indexing line_ends[i - 1].
2009-11-27 14:10:48 +00:00
if ( position <= line _ends [ 0 ] ) {
2009-06-09 07:03:21 +00:00
return 0 ;
}
// Binary search to find line # from position range.
while ( upper >= 1 ) {
var i = ( lower + upper ) >> 1 ;
2009-11-27 14:10:48 +00:00
if ( position > line _ends [ i ] ) {
2009-06-09 07:03:21 +00:00
lower = i + 1 ;
2009-11-27 14:10:48 +00:00
} else if ( position <= line _ends [ i - 1 ] ) {
2009-06-09 07:03:21 +00:00
upper = i - 1 ;
} else {
return i ;
}
}
2011-02-08 07:49:59 +00:00
2009-06-09 07:03:21 +00:00
return - 1 ;
}
2008-07-03 15:10:15 +00:00
/ * *
* Get information on a specific source position .
* @ param { number } position The source position
2009-03-09 17:59:25 +00:00
* @ param { boolean } include _resource _offset Set to true to have the resource
* offset added to the location
2008-07-03 15:10:15 +00:00
* @ return { SourceLocation }
* If line is negative or not in the source null is returned .
* /
2009-03-09 17:59:25 +00:00
Script . prototype . locationFromPosition = function ( position ,
include _resource _offset ) {
2009-06-09 07:03:21 +00:00
var line = this . lineFromPosition ( position ) ;
2008-07-03 15:10:15 +00:00
if ( line == - 1 ) return null ;
2008-08-22 13:33:59 +00:00
2008-07-03 15:10:15 +00:00
// Determine start, end and column.
2009-11-27 14:10:48 +00:00
var line _ends = this . line _ends ;
var start = line == 0 ? 0 : line _ends [ line - 1 ] + 1 ;
var end = line _ends [ line ] ;
2011-01-28 10:33:10 +00:00
if ( end > 0 && % _CallFunction ( this . source , end - 1 , StringCharAt ) == '\r' ) end -- ;
2008-07-03 15:10:15 +00:00
var column = position - start ;
// Adjust according to the offset within the resource.
2009-03-09 17:59:25 +00:00
if ( include _resource _offset ) {
line += this . line _offset ;
if ( line == this . line _offset ) {
column += this . column _offset ;
}
2008-07-03 15:10:15 +00:00
}
return new SourceLocation ( this , position , line , column , start , end ) ;
} ;
/ * *
* Get information on a specific source line and column possibly offset by a
* fixed source position . This function is used to find a source position from
* a line and column position . The fixed source position offset is typically
* used to find a source position in a function based on a line and column in
* the source for the function alone . The offset passed will then be the
* start position of the source for the function within the full script source .
* @ param { number } opt _line The line within the source . Default value is 0
* @ param { number } opt _column The column in within the line . Default value is 0
* @ param { number } opt _offset _position The offset from the begining of the
* source from where the line and column calculation starts . Default value is 0
* @ return { SourceLocation }
* If line is negative or not in the source null is returned .
* /
Script . prototype . locationFromLine = function ( opt _line , opt _column , opt _offset _position ) {
// Default is the first line in the script. Lines in the script is relative
// to the offset within the resource.
var line = 0 ;
if ( ! IS _UNDEFINED ( opt _line ) ) {
line = opt _line - this . line _offset ;
}
2008-08-22 13:33:59 +00:00
2008-07-03 15:10:15 +00:00
// Default is first column. If on the first line add the offset within the
// resource.
var column = opt _column || 0 ;
if ( line == 0 ) {
column -= this . column _offset
}
var offset _position = opt _offset _position || 0 ;
if ( line < 0 || column < 0 || offset _position < 0 ) return null ;
if ( line == 0 ) {
2009-03-12 14:03:05 +00:00
return this . locationFromPosition ( offset _position + column , false ) ;
2008-07-03 15:10:15 +00:00
} else {
2009-06-09 07:03:21 +00:00
// Find the line where the offset position is located.
var offset _line = this . lineFromPosition ( offset _position ) ;
if ( offset _line == - 1 || offset _line + line >= this . lineCount ( ) ) {
return null ;
2008-07-03 15:10:15 +00:00
}
2009-06-09 07:03:21 +00:00
2009-02-04 12:07:45 +00:00
return this . locationFromPosition ( this . line _ends [ offset _line + line - 1 ] + 1 + column ) ; // line > 0 here.
2008-07-03 15:10:15 +00:00
}
}
/ * *
* Get a slice of source code from the script . The boundaries for the slice is
* specified in lines .
* @ param { number } opt _from _line The first line ( zero bound ) in the slice .
* Default is 0
* @ param { number } opt _to _column The last line ( zero bound ) in the slice ( non
* inclusive ) . Default is the number of lines in the script
* @ return { SourceSlice } The source slice or null of the parameters where
* invalid
* /
Script . prototype . sourceSlice = function ( opt _from _line , opt _to _line ) {
var from _line = IS _UNDEFINED ( opt _from _line ) ? this . line _offset : opt _from _line ;
var to _line = IS _UNDEFINED ( opt _to _line ) ? this . line _offset + this . lineCount ( ) : opt _to _line
// Adjust according to the offset within the resource.
from _line -= this . line _offset ;
to _line -= this . line _offset ;
if ( from _line < 0 ) from _line = 0 ;
if ( to _line > this . lineCount ( ) ) to _line = this . lineCount ( ) ;
2009-02-04 12:07:45 +00:00
// Check parameters.
2008-07-03 15:10:15 +00:00
if ( from _line >= this . lineCount ( ) ||
to _line < 0 ||
from _line > to _line ) {
return null ;
}
2009-11-27 14:10:48 +00:00
var line _ends = this . line _ends ;
var from _position = from _line == 0 ? 0 : line _ends [ from _line - 1 ] + 1 ;
var to _position = to _line == 0 ? 0 : line _ends [ to _line - 1 ] + 1 ;
2008-07-03 15:10:15 +00:00
// Return a source slice with line numbers re-adjusted to the resource.
return new SourceSlice ( this , from _line + this . line _offset , to _line + this . line _offset ,
from _position , to _position ) ;
}
Script . prototype . sourceLine = function ( opt _line ) {
// Default is the first line in the script. Lines in the script are relative
// to the offset within the resource.
var line = 0 ;
if ( ! IS _UNDEFINED ( opt _line ) ) {
line = opt _line - this . line _offset ;
}
2009-02-04 12:07:45 +00:00
// Check parameter.
2008-07-03 15:10:15 +00:00
if ( line < 0 || this . lineCount ( ) <= line ) {
return null ;
}
2009-02-04 12:07:45 +00:00
// Return the source line.
2009-11-27 14:10:48 +00:00
var line _ends = this . line _ends ;
var start = line == 0 ? 0 : line _ends [ line - 1 ] + 1 ;
var end = line _ends [ line ] ;
2011-01-28 10:33:10 +00:00
return % _CallFunction ( this . source , start , end , StringSubstring ) ;
2008-07-03 15:10:15 +00:00
}
/ * *
* Returns the number of source lines .
* @ return { number }
* Number of source lines .
* /
Script . prototype . lineCount = function ( ) {
2009-02-04 12:07:45 +00:00
// Return number of source lines.
return this . line _ends . length ;
2008-07-03 15:10:15 +00:00
} ;
2010-04-01 16:25:07 +00:00
/ * *
* Returns the name of script if available , contents of sourceURL comment
2010-10-15 13:03:59 +00:00
* otherwise . See
2010-04-01 16:25:07 +00:00
* http : //fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
* for details on using //@ sourceURL comment to identify scritps that don't
* have name .
2010-10-15 13:03:59 +00:00
*
2010-04-01 16:25:07 +00:00
* @ return { ? string } script name if present , value for //@ sourceURL comment
* otherwise .
* /
Script . prototype . nameOrSourceURL = function ( ) {
if ( this . name )
return this . name ;
2010-10-15 13:03:59 +00:00
// TODO(608): the spaces in a regexp below had to be escaped as \040
2010-04-01 16:25:07 +00:00
// because this file is being processed by js2c whose handling of spaces
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
// avoid matches against sources that invoke evals with sourceURL.
2011-03-18 13:40:48 +00:00
// A better solution would be to detect these special comments in
// the scanner/parser.
var source = ToString ( this . source ) ;
var sourceUrlPos = % StringIndexOf ( source , "sourceURL=" , 0 ) ;
if ( sourceUrlPos > 4 ) {
var sourceUrlPattern =
/\/\/@[\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm ;
// Don't reuse lastMatchInfo here, so we create a new array with room
// for four captures (array with length one longer than the index
// of the fourth capture, where the numbering is zero-based).
var matchInfo = new InternalArray ( CAPTURE ( 3 ) + 1 ) ;
var match =
% _RegExpExec ( sourceUrlPattern , source , sourceUrlPos - 4 , matchInfo ) ;
if ( match ) {
return SubString ( source , matchInfo [ CAPTURE ( 2 ) ] , matchInfo [ CAPTURE ( 3 ) ] ) ;
}
}
return this . name ;
2010-04-01 16:25:07 +00:00
}
2008-07-03 15:10:15 +00:00
/ * *
* Class for source location . A source location is a position within some
* source with the following properties :
* script : script object for the source
* line : source line number
* column : source column within the line
* position : position within the source
* start : position of start of source context ( inclusive )
* end : position of end of source context ( not inclusive )
* Source text for the source context is the character interval [ start , end [ . In
* most cases end will point to a newline character . It might point just past
* the final position of the source if the last source line does not end with a
2009-02-04 12:07:45 +00:00
* newline character .
2008-07-03 15:10:15 +00:00
* @ param { Script } script The Script object for which this is a location
* @ param { number } position Source position for the location
* @ param { number } line The line number for the location
* @ param { number } column The column within the line for the location
* @ param { number } start Source position for start of source context
* @ param { number } end Source position for end of source context
* @ constructor
* /
function SourceLocation ( script , position , line , column , start , end ) {
this . script = script ;
this . position = position ;
this . line = line ;
this . column = column ;
this . start = start ;
this . end = end ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
const kLineLengthLimit = 78 ;
/ * *
* Restrict source location start and end positions to make the source slice
* no more that a certain number of characters wide .
* @ param { number } opt _limit The with limit of the source text with a default
* of 78
* @ param { number } opt _before The number of characters to prefer before the
* position with a default value of 10 less that the limit
* /
SourceLocation . prototype . restrict = function ( opt _limit , opt _before ) {
// Find the actual limit to use.
var limit ;
var before ;
if ( ! IS _UNDEFINED ( opt _limit ) ) {
limit = opt _limit ;
} else {
limit = kLineLengthLimit ;
}
if ( ! IS _UNDEFINED ( opt _before ) ) {
before = opt _before ;
} else {
// If no before is specified center for small limits and perfer more source
// before the the position that after for longer limits.
if ( limit <= 20 ) {
2008-10-03 07:14:31 +00:00
before = $floor ( limit / 2 ) ;
2008-07-03 15:10:15 +00:00
} else {
before = limit - 10 ;
}
}
if ( before >= limit ) {
before = limit - 1 ;
}
// If the [start, end[ interval is too big we restrict
// it in one or both ends. We make sure to always produce
// restricted intervals of maximum allowed size.
if ( this . end - this . start > limit ) {
var start _limit = this . position - before ;
var end _limit = this . position + limit - before ;
if ( this . start < start _limit && end _limit < this . end ) {
this . start = start _limit ;
this . end = end _limit ;
} else if ( this . start < start _limit ) {
this . start = this . end - limit ;
} else {
this . end = this . start + limit ;
}
}
} ;
/ * *
* Get the source text for a SourceLocation
* @ return { String }
* Source text for this location .
* /
SourceLocation . prototype . sourceText = function ( ) {
2011-01-28 10:33:10 +00:00
return % _CallFunction ( this . script . source , this . start , this . end , StringSubstring ) ;
2008-07-03 15:10:15 +00:00
} ;
/ * *
* Class for a source slice . A source slice is a part of a script source with
* the following properties :
* script : script object for the source
* from _line : line number for the first line in the slice
* to _line : source line number for the last line in the slice
* from _position : position of the first character in the slice
* to _position : position of the last character in the slice
* The to _line and to _position are not included in the slice , that is the lines
* in the slice are [ from _line , to _line [ . Likewise the characters in the slice
* are [ from _position , to _position [ .
* @ param { Script } script The Script object for the source slice
* @ param { number } from _line
* @ param { number } to _line
* @ param { number } from _position
* @ param { number } to _position
* @ constructor
* /
function SourceSlice ( script , from _line , to _line , from _position , to _position ) {
this . script = script ;
this . from _line = from _line ;
this . to _line = to _line ;
this . from _position = from _position ;
this . to _position = to _position ;
}
/ * *
* Get the source text for a SourceSlice
* @ return { String } Source text for this slice . The last line will include
* the line terminating characters ( if any )
* /
SourceSlice . prototype . sourceText = function ( ) {
2011-01-28 10:33:10 +00:00
return % _CallFunction ( this . script . source ,
this . from _position ,
this . to _position ,
StringSubstring ) ;
2008-07-03 15:10:15 +00:00
} ;
// Returns the offset of the given position within the containing
// line.
function GetPositionInLine ( message ) {
2011-02-02 13:31:52 +00:00
var script = % MessageGetScript ( message ) ;
var start _position = % MessageGetStartPosition ( message ) ;
var location = script . locationFromPosition ( start _position , false ) ;
2008-07-03 15:10:15 +00:00
if ( location == null ) return - 1 ;
location . restrict ( ) ;
2011-02-02 13:31:52 +00:00
return start _position - location . start ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
function GetStackTraceLine ( recv , fun , pos , isGlobal ) {
2009-06-30 11:08:37 +00:00
return FormatSourcePosition ( new CallSite ( recv , fun , pos ) ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
// ----------------------------------------------------------------------------
// Error implementation
2009-03-09 12:50:32 +00:00
// Defines accessors for a property that is calculated the first time
2009-07-27 12:01:32 +00:00
// the property is read.
2009-03-19 15:06:00 +00:00
function DefineOneShotAccessor ( obj , name , fun ) {
2009-03-09 12:50:32 +00:00
// Note that the accessors consistently operate on 'obj', not 'this'.
// Since the object may occur in someone else's prototype chain we
// can't rely on 'this' being the same as 'obj'.
2009-07-27 12:01:32 +00:00
var hasBeenSet = false ;
var value ;
2009-03-09 12:50:32 +00:00
obj . _ _defineGetter _ _ ( name , function ( ) {
2009-07-27 12:01:32 +00:00
if ( hasBeenSet ) {
return value ;
}
hasBeenSet = true ;
value = fun ( obj ) ;
2009-03-09 12:50:32 +00:00
return value ;
} ) ;
2009-03-19 15:06:00 +00:00
obj . _ _defineSetter _ _ ( name , function ( v ) {
2009-07-27 12:01:32 +00:00
hasBeenSet = true ;
value = v ;
2009-03-19 15:06:00 +00:00
} ) ;
2009-03-09 12:50:32 +00:00
}
2009-06-30 11:08:37 +00:00
function CallSite ( receiver , fun , pos ) {
this . receiver = receiver ;
this . fun = fun ;
this . pos = pos ;
}
CallSite . prototype . getThis = function ( ) {
return this . receiver ;
} ;
CallSite . prototype . getTypeName = function ( ) {
var constructor = this . receiver . constructor ;
if ( ! constructor )
2011-01-28 10:33:10 +00:00
return % _CallFunction ( this . receiver , ObjectToString ) ;
2009-06-30 11:08:37 +00:00
var constructorName = constructor . name ;
if ( ! constructorName )
2011-01-28 10:33:10 +00:00
return % _CallFunction ( this . receiver , ObjectToString ) ;
2009-06-30 11:08:37 +00:00
return constructorName ;
} ;
CallSite . prototype . isToplevel = function ( ) {
if ( this . receiver == null )
return true ;
return IS _GLOBAL ( this . receiver ) ;
} ;
CallSite . prototype . isEval = function ( ) {
var script = % FunctionGetScript ( this . fun ) ;
2010-03-23 11:40:38 +00:00
return script && script . compilation _type == COMPILATION _TYPE _EVAL ;
2009-06-30 11:08:37 +00:00
} ;
CallSite . prototype . getEvalOrigin = function ( ) {
var script = % FunctionGetScript ( this . fun ) ;
2009-12-01 14:36:45 +00:00
return FormatEvalOrigin ( script ) ;
2009-06-30 11:08:37 +00:00
} ;
2010-09-20 15:55:28 +00:00
CallSite . prototype . getScriptNameOrSourceURL = function ( ) {
var script = % FunctionGetScript ( this . fun ) ;
return script ? script . nameOrSourceURL ( ) : null ;
} ;
2009-07-02 15:30:03 +00:00
CallSite . prototype . getFunction = function ( ) {
return this . fun ;
} ;
2009-06-30 11:08:37 +00:00
CallSite . prototype . getFunctionName = function ( ) {
// See if the function knows its own name
var name = this . fun . name ;
2009-07-02 12:26:31 +00:00
if ( name ) {
2009-06-30 11:08:37 +00:00
return name ;
2009-07-02 12:26:31 +00:00
} else {
return % FunctionGetInferredName ( this . fun ) ;
}
// Maybe this is an evaluation?
var script = % FunctionGetScript ( this . fun ) ;
2010-03-23 11:40:38 +00:00
if ( script && script . compilation _type == COMPILATION _TYPE _EVAL )
2009-07-02 12:26:31 +00:00
return "eval" ;
return null ;
} ;
CallSite . prototype . getMethodName = function ( ) {
2009-06-30 11:08:37 +00:00
// See if we can find a unique property on the receiver that holds
// this function.
2009-07-02 15:30:03 +00:00
var ownName = this . fun . name ;
2010-08-13 08:31:52 +00:00
if ( ownName && this . receiver &&
2011-01-28 10:33:10 +00:00
( % _CallFunction ( this . receiver , ownName , ObjectLookupGetter ) === this . fun ||
% _CallFunction ( this . receiver , ownName , ObjectLookupSetter ) === this . fun ||
2010-08-13 08:31:52 +00:00
this . receiver [ ownName ] === this . fun ) ) {
2009-07-02 15:30:03 +00:00
// To handle DontEnum properties we guess that the method has
// the same name as the function.
return ownName ;
2010-08-13 08:31:52 +00:00
}
2009-07-02 12:26:31 +00:00
var name = null ;
2009-06-30 11:08:37 +00:00
for ( var prop in this . receiver ) {
2010-08-13 08:31:52 +00:00
if ( this . receiver . _ _lookupGetter _ _ ( prop ) === this . fun ||
this . receiver . _ _lookupSetter _ _ ( prop ) === this . fun ||
( ! this . receiver . _ _lookupGetter _ _ ( prop ) && this . receiver [ prop ] === this . fun ) ) {
// If we find more than one match bail out to avoid confusion.
2009-06-30 11:08:37 +00:00
if ( name )
return null ;
name = prop ;
}
}
if ( name )
return name ;
return null ;
} ;
CallSite . prototype . getFileName = function ( ) {
var script = % FunctionGetScript ( this . fun ) ;
return script ? script . name : null ;
} ;
CallSite . prototype . getLineNumber = function ( ) {
if ( this . pos == - 1 )
return null ;
var script = % FunctionGetScript ( this . fun ) ;
var location = null ;
if ( script ) {
location = script . locationFromPosition ( this . pos , true ) ;
}
return location ? location . line + 1 : null ;
} ;
CallSite . prototype . getColumnNumber = function ( ) {
if ( this . pos == - 1 )
return null ;
var script = % FunctionGetScript ( this . fun ) ;
var location = null ;
if ( script ) {
location = script . locationFromPosition ( this . pos , true ) ;
}
2009-12-01 14:36:45 +00:00
return location ? location . column + 1 : null ;
2009-06-30 11:08:37 +00:00
} ;
CallSite . prototype . isNative = function ( ) {
var script = % FunctionGetScript ( this . fun ) ;
2010-03-23 11:40:38 +00:00
return script ? ( script . type == TYPE _NATIVE ) : false ;
2009-06-30 11:08:37 +00:00
} ;
CallSite . prototype . getPosition = function ( ) {
return this . pos ;
} ;
CallSite . prototype . isConstructor = function ( ) {
var constructor = this . receiver ? this . receiver . constructor : null ;
if ( ! constructor )
return false ;
return this . fun === constructor ;
} ;
2009-12-01 14:36:45 +00:00
function FormatEvalOrigin ( script ) {
2010-09-20 15:55:28 +00:00
var sourceURL = script . nameOrSourceURL ( ) ;
if ( sourceURL )
return sourceURL ;
var eval _origin = "eval at " ;
2009-12-01 14:36:45 +00:00
if ( script . eval _from _function _name ) {
eval _origin += script . eval _from _function _name ;
} else {
eval _origin += "<anonymous>" ;
}
2010-03-30 07:15:23 +00:00
2009-12-01 14:36:45 +00:00
var eval _from _script = script . eval _from _script ;
if ( eval _from _script ) {
2010-03-23 11:40:38 +00:00
if ( eval _from _script . compilation _type == COMPILATION _TYPE _EVAL ) {
2009-12-01 14:36:45 +00:00
// eval script originated from another eval.
2010-09-20 15:55:28 +00:00
eval _origin += " (" + FormatEvalOrigin ( eval _from _script ) + ")" ;
2009-12-01 14:36:45 +00:00
} else {
2010-09-20 15:55:28 +00:00
// eval script originated from "real" source.
2009-12-01 14:36:45 +00:00
if ( eval _from _script . name ) {
eval _origin += " (" + eval _from _script . name ;
var location = eval _from _script . locationFromPosition ( script . eval _from _script _position , true ) ;
if ( location ) {
eval _origin += ":" + ( location . line + 1 ) ;
eval _origin += ":" + ( location . column + 1 ) ;
}
eval _origin += ")"
} else {
eval _origin += " (unknown source)" ;
}
}
}
2010-03-30 07:15:23 +00:00
2009-12-01 14:36:45 +00:00
return eval _origin ;
} ;
2009-06-30 11:08:37 +00:00
function FormatSourcePosition ( frame ) {
2010-09-20 15:55:28 +00:00
var fileName ;
2009-06-30 11:08:37 +00:00
var fileLocation = "" ;
if ( frame . isNative ( ) ) {
fileLocation = "native" ;
} else if ( frame . isEval ( ) ) {
2010-09-20 15:55:28 +00:00
fileName = frame . getScriptNameOrSourceURL ( ) ;
if ( ! fileName )
fileLocation = frame . getEvalOrigin ( ) ;
2009-06-30 11:08:37 +00:00
} else {
2010-09-20 15:55:28 +00:00
fileName = frame . getFileName ( ) ;
}
if ( fileName ) {
fileLocation += fileName ;
var lineNumber = frame . getLineNumber ( ) ;
if ( lineNumber != null ) {
fileLocation += ":" + lineNumber ;
var columnNumber = frame . getColumnNumber ( ) ;
if ( columnNumber ) {
fileLocation += ":" + columnNumber ;
2009-06-30 11:08:37 +00:00
}
}
}
2010-09-20 15:55:28 +00:00
2009-06-30 11:08:37 +00:00
if ( ! fileLocation ) {
fileLocation = "unknown source" ;
}
var line = "" ;
2009-07-02 15:30:03 +00:00
var functionName = frame . getFunction ( ) . name ;
2009-07-02 12:26:31 +00:00
var addPrefix = true ;
2009-07-02 15:30:03 +00:00
var isConstructor = frame . isConstructor ( ) ;
var isMethodCall = ! ( frame . isToplevel ( ) || isConstructor ) ;
if ( isMethodCall ) {
2010-09-06 09:10:11 +00:00
var methodName = frame . getMethodName ( ) ;
2009-07-02 15:30:03 +00:00
line += frame . getTypeName ( ) + "." ;
if ( functionName ) {
line += functionName ;
if ( methodName && ( methodName != functionName ) ) {
line += " [as " + methodName + "]" ;
}
} else {
line += methodName || "<anonymous>" ;
}
} else if ( isConstructor ) {
line += "new " + ( functionName || "<anonymous>" ) ;
2009-07-02 12:26:31 +00:00
} else if ( functionName ) {
line += functionName ;
2009-06-30 11:08:37 +00:00
} else {
line += fileLocation ;
2009-07-02 12:26:31 +00:00
addPrefix = false ;
}
if ( addPrefix ) {
2009-07-02 15:30:03 +00:00
line += " (" + fileLocation + ")" ;
2009-06-30 11:08:37 +00:00
}
return line ;
}
function FormatStackTrace ( error , frames ) {
var lines = [ ] ;
try {
lines . push ( error . toString ( ) ) ;
} catch ( e ) {
try {
lines . push ( "<error: " + e + ">" ) ;
} catch ( ee ) {
lines . push ( "<error>" ) ;
}
}
for ( var i = 0 ; i < frames . length ; i ++ ) {
var frame = frames [ i ] ;
2009-09-23 12:32:24 +00:00
var line ;
2009-06-30 11:08:37 +00:00
try {
2009-09-23 12:32:24 +00:00
line = FormatSourcePosition ( frame ) ;
2009-06-30 11:08:37 +00:00
} catch ( e ) {
try {
2009-09-23 12:32:24 +00:00
line = "<error: " + e + ">" ;
2009-06-30 11:08:37 +00:00
} catch ( ee ) {
// Any code that reaches this point is seriously nasty!
2009-09-23 12:32:24 +00:00
line = "<error>" ;
2009-06-30 11:08:37 +00:00
}
}
lines . push ( " at " + line ) ;
}
return lines . join ( "\n" ) ;
}
function FormatRawStackTrace ( error , raw _stack ) {
var frames = [ ] ;
2010-12-07 11:31:57 +00:00
for ( var i = 0 ; i < raw _stack . length ; i += 4 ) {
2009-06-30 11:08:37 +00:00
var recv = raw _stack [ i ] ;
2010-12-07 11:31:57 +00:00
var fun = raw _stack [ i + 1 ] ;
var code = raw _stack [ i + 2 ] ;
var pc = raw _stack [ i + 3 ] ;
var pos = % FunctionGetPositionForOffset ( code , pc ) ;
2009-06-30 11:08:37 +00:00
frames . push ( new CallSite ( recv , fun , pos ) ) ;
}
if ( IS _FUNCTION ( $Error . prepareStackTrace ) ) {
return $Error . prepareStackTrace ( error , frames ) ;
} else {
return FormatStackTrace ( error , frames ) ;
}
}
2008-10-03 07:14:31 +00:00
function DefineError ( f ) {
2008-07-03 15:10:15 +00:00
// Store the error function in both the global object
// and the runtime object. The function is fetched
// from the runtime object when throwing errors from
// within the runtime system to avoid strange side
// effects when overwriting the error functions from
// user code.
2008-10-03 07:14:31 +00:00
var name = f . name ;
2008-10-03 12:14:29 +00:00
% SetProperty ( global , name , f , DONT _ENUM ) ;
2008-07-03 15:10:15 +00:00
this [ '$' + name ] = f ;
// Configure the error function.
2009-03-10 11:32:19 +00:00
if ( name == 'Error' ) {
// The prototype of the Error object must itself be an error.
// However, it can't be an instance of the Error object because
// it hasn't been properly configured yet. Instead we create a
// special not-a-true-error-but-close-enough object.
function ErrorPrototype ( ) { }
2009-03-10 13:15:24 +00:00
% FunctionSetPrototype ( ErrorPrototype , $Object . prototype ) ;
2009-03-10 11:32:19 +00:00
% FunctionSetInstanceClassName ( ErrorPrototype , 'Error' ) ;
% FunctionSetPrototype ( f , new ErrorPrototype ( ) ) ;
} else {
% FunctionSetPrototype ( f , new $Error ( ) ) ;
}
2008-07-03 15:10:15 +00:00
% FunctionSetInstanceClassName ( f , 'Error' ) ;
2008-10-06 12:53:02 +00:00
% SetProperty ( f . prototype , 'constructor' , f , DONT _ENUM ) ;
2011-01-14 12:51:04 +00:00
// The name property on the prototype of error objects is not
// specified as being read-one and dont-delete. However, allowing
// overwriting allows leaks of error objects between script blocks
// in the same context in a browser setting. Therefore we fix the
// name.
% SetProperty ( f . prototype , "name" , name , READ _ONLY | DONT _DELETE ) ;
2008-07-03 15:10:15 +00:00
% SetCode ( f , function ( m ) {
2009-06-29 08:14:06 +00:00
if ( % _IsConstructCall ( ) ) {
2011-01-13 06:56:54 +00:00
// Define all the expected properties directly on the error
// object. This avoids going through getters and setters defined
// on prototype objects.
% IgnoreAttributesAndSetProperty ( this , 'stack' , void 0 ) ;
% IgnoreAttributesAndSetProperty ( this , 'arguments' , void 0 ) ;
% IgnoreAttributesAndSetProperty ( this , 'type' , void 0 ) ;
2009-03-09 12:50:32 +00:00
if ( m === kAddMessageAccessorsMarker ) {
2011-01-13 06:56:54 +00:00
// DefineOneShotAccessor always inserts a message property and
// ignores setters.
2009-03-09 12:50:32 +00:00
DefineOneShotAccessor ( this , 'message' , function ( obj ) {
2011-02-02 13:31:52 +00:00
return FormatMessage ( % NewMessageObject ( obj . type , obj . arguments ) ) ;
2009-03-19 15:06:00 +00:00
} ) ;
2009-03-09 12:50:32 +00:00
} else if ( ! IS _UNDEFINED ( m ) ) {
2011-01-13 06:56:54 +00:00
% IgnoreAttributesAndSetProperty ( this , 'message' , ToString ( m ) ) ;
2009-03-09 12:50:32 +00:00
}
2009-07-27 12:01:32 +00:00
captureStackTrace ( this , f ) ;
2008-07-03 15:10:15 +00:00
} else {
return new f ( m ) ;
}
} ) ;
2008-10-03 07:14:31 +00:00
}
2008-07-03 15:10:15 +00:00
2009-07-27 12:01:32 +00:00
function captureStackTrace ( obj , cons _opt ) {
var stackTraceLimit = $Error . stackTraceLimit ;
2011-02-02 13:31:52 +00:00
if ( ! stackTraceLimit || ! IS _NUMBER ( stackTraceLimit ) ) return ;
2009-07-27 12:01:32 +00:00
if ( stackTraceLimit < 0 || stackTraceLimit > 10000 )
stackTraceLimit = 10000 ;
2011-02-02 13:31:52 +00:00
var raw _stack = % CollectStackTrace ( cons _opt
? cons _opt
: captureStackTrace , stackTraceLimit ) ;
2009-07-27 12:01:32 +00:00
DefineOneShotAccessor ( obj , 'stack' , function ( obj ) {
return FormatRawStackTrace ( obj , raw _stack ) ;
} ) ;
} ;
2008-07-03 15:10:15 +00:00
$Math . _ _proto _ _ = global . Object . prototype ;
2008-10-03 07:14:31 +00:00
DefineError ( function Error ( ) { } ) ;
DefineError ( function TypeError ( ) { } ) ;
DefineError ( function RangeError ( ) { } ) ;
DefineError ( function SyntaxError ( ) { } ) ;
DefineError ( function ReferenceError ( ) { } ) ;
DefineError ( function EvalError ( ) { } ) ;
DefineError ( function URIError ( ) { } ) ;
2008-07-03 15:10:15 +00:00
2009-07-27 12:01:32 +00:00
$Error . captureStackTrace = captureStackTrace ;
2008-07-03 15:10:15 +00:00
// Setup extra properties of the Error.prototype object.
$Error . prototype . message = '' ;
2011-01-21 11:44:29 +00:00
// Global list of error objects visited during errorToString. This is
// used to detect cycles in error toString formatting.
var visited _errors = new $Array ( ) ;
var cyclic _error _marker = new $Object ( ) ;
function errorToStringDetectCycle ( ) {
if ( ! % PushIfAbsent ( visited _errors , this ) ) throw cyclic _error _marker ;
try {
var type = this . type ;
2011-02-01 12:31:16 +00:00
if ( type && ! % _CallFunction ( this , "message" , ObjectHasOwnProperty ) ) {
2011-02-02 13:31:52 +00:00
var formatted = FormatMessage ( % NewMessageObject ( type , this . arguments ) ) ;
2011-01-21 11:44:29 +00:00
return this . name + ": " + formatted ;
}
2011-02-01 12:31:16 +00:00
var message = % _CallFunction ( this , "message" , ObjectHasOwnProperty )
? ( ": " + this . message )
: "" ;
2011-01-21 11:44:29 +00:00
return this . name + message ;
} finally {
2011-02-01 12:31:16 +00:00
visited _errors . length = visited _errors . length - 1 ;
2011-01-21 11:44:29 +00:00
}
}
2011-01-14 12:51:04 +00:00
function errorToString ( ) {
2011-05-05 05:21:30 +00:00
if ( IS _NULL _OR _UNDEFINED ( this ) && ! IS _UNDETECTABLE ( this ) ) {
throw MakeTypeError ( "called_on_null_or_undefined" ,
[ "Error.prototype.toString" ] ) ;
}
2011-01-21 14:11:35 +00:00
// This helper function is needed because access to properties on
2011-01-21 11:44:29 +00:00
// the builtins object do not work inside of a catch clause.
function isCyclicErrorMarker ( o ) { return o === cyclic _error _marker ; }
try {
return % _CallFunction ( this , errorToStringDetectCycle ) ;
} catch ( e ) {
2011-01-21 14:11:35 +00:00
// If this error message was encountered already return the empty
// string for it instead of recursively formatting it.
if ( isCyclicErrorMarker ( e ) ) return '' ;
2011-01-21 11:44:29 +00:00
else throw e ;
2008-07-03 15:10:15 +00:00
}
2011-01-14 12:51:04 +00:00
}
2011-01-14 14:51:19 +00:00
2011-02-28 13:29:05 +00:00
InstallFunctions ( $Error . prototype , DONT _ENUM , [ 'toString' , errorToString ] ) ;
2008-07-03 15:10:15 +00:00
// Boilerplate for exceptions for stack overflows. Used from
2011-03-18 20:35:07 +00:00
// Isolate::StackOverflow().
2008-07-03 15:10:15 +00:00
const kStackOverflowBoilerplate = MakeRangeError ( 'stack_overflow' , [ ] ) ;