| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:mirrors' show MirrorSystem; | |
| patch class Error { | |
| /* patch */ static String _objectToString(Object object) { | |
| return Object._toString(object); | |
| } | |
| /* patch */ StackTrace get stackTrace => _stackTrace; | |
| StackTrace _stackTrace; | |
| } | |
| patch class AssertionError extends Error { | |
| AssertionError._create( | |
| this._failedAssertion, this._url, this._line, this._column); | |
| static _throwNew(int assertionStart, int assertionEnd) | |
| native "AssertionError_throwNew"; | |
| String toString() { | |
| var columnInfo = ""; | |
| if (_column > 0) { | |
| // Only add column information if it is valid. | |
| columnInfo = " pos $_column"; | |
| } | |
| return "'$_url': Failed assertion: line $_line$columnInfo: " | |
| "'$_failedAssertion' is not true."; | |
| } | |
| final String _failedAssertion; | |
| final String _url; | |
| final int _line; | |
| final int _column; | |
| } | |
| patch class TypeError extends AssertionError { | |
| TypeError._create(String url, int line, int column, | |
| this._srcType, this._dstType, this._dstName, | |
| this._errorMsg) | |
| : super._create("is assignable", url, line, column); | |
| static _throwNew(int location, | |
| Object src_value, | |
| String dst_type_name, | |
| String dst_name, | |
| String error_msg) | |
| native "TypeError_throwNew"; | |
| String toString() { | |
| String str = (_errorMsg != null) ? _errorMsg : ""; | |
| if ((_dstName != null) && (_dstName.length > 0)) { | |
| str = "${str}type '$_srcType' is not a subtype of " | |
| "type '$_dstType' of '$_dstName'."; | |
| } else { | |
| str = "${str}type error."; | |
| } | |
| return str; | |
| } | |
| final String _srcType; | |
| final String _dstType; | |
| final String _dstName; | |
| final String _errorMsg; | |
| } | |
| patch class CastError extends Error { | |
| CastError._create(this._url, this._line, this._column, | |
| this._srcType, this._dstType, this._dstName, | |
| this._errorMsg); | |
| // A CastError is allocated by TypeError._throwNew() when dst_name equals | |
| // Exceptions::kCastErrorDstName. | |
| String toString() { | |
| String str = (_errorMsg != null) ? _errorMsg : ""; | |
| str = "${str}type '$_srcType' is not a subtype of " | |
| "type '$_dstType' in type cast."; | |
| return str; | |
| } | |
| // Fields _url, _line, and _column are only used for debugging purposes. | |
| final String _url; | |
| final int _line; | |
| final int _column; | |
| final String _srcType; | |
| final String _dstType; | |
| final String _dstName; | |
| final String _errorMsg; | |
| } | |
| patch class FallThroughError { | |
| FallThroughError._create(this._url, this._line); | |
| static _throwNew(int case_clause_pos) native "FallThroughError_throwNew"; | |
| /* patch */ String toString() { | |
| return "'$_url': Switch case fall-through at line $_line."; | |
| } | |
| // These new fields cannot be declared final, because a constructor exists | |
| // in the original version of this patched class. | |
| String _url; | |
| int _line; | |
| } | |
| class _InternalError { | |
| const _InternalError(this._msg); | |
| String toString() => "InternalError: '${_msg}'"; | |
| final String _msg; | |
| } | |
| patch class CyclicInitializationError { | |
| static _throwNew(String variableName) { | |
| throw new CyclicInitializationError(variableName); | |
| } | |
| } | |
| patch class AbstractClassInstantiationError { | |
| AbstractClassInstantiationError._create( | |
| this._className, this._url, this._line); | |
| static _throwNew(int case_clause_pos, String className) | |
| native "AbstractClassInstantiationError_throwNew"; | |
| /* patch */ String toString() { | |
| return "Cannot instantiate abstract class $_className: " | |
| "_url '$_url' line $_line"; | |
| } | |
| // These new fields cannot be declared final, because a constructor exists | |
| // in the original version of this patched class. | |
| String _url; | |
| int _line; | |
| } | |
| patch class NoSuchMethodError { | |
| // The compiler emits a call to _throwNew when it cannot resolve a static | |
| // method at compile time. The receiver is actually the literal class of the | |
| // unresolved method. | |
| static void _throwNew(Object receiver, | |
| String memberName, | |
| int invocation_type, | |
| List arguments, | |
| List argumentNames, | |
| List existingArgumentNames) { | |
| int numNamedArguments = argumentNames == null ? 0 : argumentNames.length; | |
| int numPositionalArguments = arguments == null ? 0 : arguments.length; | |
| numPositionalArguments -= numNamedArguments; | |
| List positionalArguments; | |
| if (numPositionalArguments == 0) { | |
| // Differ between no arguments specified and 0 arguments. | |
| // TODO(srdjan): This can currently occur for unresolvable static methods. | |
| // In that case, the arguments are evaluated but not passed to the | |
| // throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and | |
| // Parser::ThrowNoSuchMethodError)). | |
| positionalArguments = argumentNames == null ? null : []; | |
| } else { | |
| positionalArguments = arguments.sublist(0, numPositionalArguments); | |
| } | |
| Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>(); | |
| for (int i = 0; i < numNamedArguments; i++) { | |
| var arg_value = arguments[numPositionalArguments + i]; | |
| namedArguments[new Symbol(argumentNames[i])] = arg_value; | |
| } | |
| throw new NoSuchMethodError._withType(receiver, | |
| new Symbol(memberName), | |
| invocation_type, | |
| positionalArguments, | |
| namedArguments, | |
| existingArgumentNames); | |
| } | |
| // Remember the type from the invocation mirror or static compilation | |
| // analysis when thrown directly with _throwNew. A negative value means | |
| // that no information is available. | |
| final int _invocation_type; | |
| NoSuchMethodError(Object this._receiver, | |
| Symbol this._memberName, | |
| List this._arguments, | |
| Map<Symbol, dynamic> this._namedArguments, | |
| [List existingArgumentNames = null]) | |
| : this._existingArgumentNames = existingArgumentNames, | |
| this._invocation_type = -1; | |
| // This constructor seems to be called with either strings or | |
| // values read from another NoSuchMethodError. | |
| NoSuchMethodError._withType(Object this._receiver, | |
| /*String|Symbol*/ memberName, | |
| this._invocation_type, | |
| List this._arguments, | |
| Map<dynamic, dynamic> namedArguments, | |
| [List existingArgumentNames = null]) | |
| : this._memberName = | |
| (memberName is String) ? new Symbol(memberName) : memberName, | |
| this._namedArguments = | |
| (namedArguments == null) | |
| ? null | |
| : new Map<Symbol, dynamic>.fromIterable( | |
| namedArguments.keys, | |
| key: (k) => (k is String) ? new Symbol(k) : k, | |
| value: (k) => namedArguments[k]), | |
| this._existingArgumentNames = existingArgumentNames; | |
| String _developerMessage(args_mismatch) { | |
| if (_invocation_type < 0) { | |
| return ""; | |
| } | |
| var type = _invocation_type & _InvocationMirror._TYPE_MASK; | |
| var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) & | |
| _InvocationMirror._CALL_MASK; | |
| var type_str = | |
| (const ["method", "getter", "setter", "getter or setter", "variable"])[type]; | |
| var args_message = args_mismatch ? " with matching arguments" : ""; | |
| var msg; | |
| var memberName = | |
| (_memberName == null) ? "" : MirrorSystem.getName(_memberName); | |
| if (type == _InvocationMirror._LOCAL_VAR) { | |
| return "cannot assign to final variable '$memberName'.\n\n"; | |
| } | |
| switch (level) { | |
| case _InvocationMirror._DYNAMIC: { | |
| if (_receiver == null) { | |
| msg = "The null object does not have a $type_str '$memberName'" | |
| "$args_message."; | |
| } else { | |
| if (_receiver is Function) { | |
| msg = "Closure call with mismatched arguments: " | |
| "function '$memberName'"; | |
| } else { | |
| msg = "Class '${_receiver.runtimeType}' has no instance $type_str " | |
| "'$memberName'$args_message."; | |
| } | |
| } | |
| break; | |
| } | |
| case _InvocationMirror._SUPER: { | |
| msg = "Super class of class '${_receiver.runtimeType}' has no instance " | |
| "$type_str '$memberName'$args_message."; | |
| break; | |
| } | |
| case _InvocationMirror._STATIC: { | |
| msg = "No static $type_str '$memberName' declared in class " | |
| "'$_receiver'."; | |
| break; | |
| } | |
| case _InvocationMirror._CONSTRUCTOR: { | |
| msg = "No constructor '$memberName'$args_message declared in class '$_receiver'."; | |
| break; | |
| } | |
| case _InvocationMirror._TOP_LEVEL: { | |
| msg = "No top-level $type_str '$memberName'$args_message declared."; | |
| break; | |
| } | |
| } | |
| return "$msg\n\n"; | |
| } | |
| /* patch */ String toString() { | |
| StringBuffer actual_buf = new StringBuffer(); | |
| int i = 0; | |
| if (_arguments == null) { | |
| // Actual arguments unknown. | |
| // TODO(srdjan): Remove once arguments are passed for unresolvable | |
| // static methods. | |
| actual_buf.write("..."); | |
| } else { | |
| for (; i < _arguments.length; i++) { | |
| if (i > 0) { | |
| actual_buf.write(", "); | |
| } | |
| actual_buf.write(Error.safeToString(_arguments[i])); | |
| } | |
| } | |
| if (_namedArguments != null) { | |
| _namedArguments.forEach((Symbol key, var value) { | |
| if (i > 0) { | |
| actual_buf.write(", "); | |
| } | |
| actual_buf.write(MirrorSystem.getName(key)); | |
| actual_buf.write(": "); | |
| actual_buf.write(Error.safeToString(value)); | |
| i++; | |
| }); | |
| } | |
| var args_mismatch = _existingArgumentNames != null; | |
| StringBuffer msg_buf = new StringBuffer(_developerMessage(args_mismatch)); | |
| String receiver_str; | |
| var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) & | |
| _InvocationMirror._CALL_MASK; | |
| if ( level == _InvocationMirror._TOP_LEVEL) { | |
| receiver_str = "top-level"; | |
| } else { | |
| receiver_str = Error.safeToString(_receiver); | |
| } | |
| var memberName = | |
| (_memberName == null) ? "" : MirrorSystem.getName(_memberName); | |
| var type = _invocation_type & _InvocationMirror._TYPE_MASK; | |
| if (type == _InvocationMirror._LOCAL_VAR) { | |
| msg_buf.write( | |
| "NoSuchMethodError: cannot assign to final variable '$memberName'"); | |
| } else if (!args_mismatch) { | |
| msg_buf.write( | |
| "NoSuchMethodError: method not found: '$memberName'\n" | |
| "Receiver: $receiver_str\n" | |
| "Arguments: [$actual_buf]"); | |
| } else { | |
| String actualParameters = actual_buf.toString(); | |
| StringBuffer formal_buf = new StringBuffer(); | |
| for (int i = 0; i < _existingArgumentNames.length; i++) { | |
| if (i > 0) { | |
| formal_buf.write(", "); | |
| } | |
| formal_buf.write(_existingArgumentNames[i]); | |
| } | |
| String formalParameters = formal_buf.toString(); | |
| msg_buf.write( | |
| "NoSuchMethodError: incorrect number of arguments passed to " | |
| "method named '$memberName'\n" | |
| "Receiver: $receiver_str\n" | |
| "Tried calling: $memberName($actualParameters)\n" | |
| "Found: $memberName($formalParameters)"); | |
| } | |
| return msg_buf.toString(); | |
| } | |
| } | |
| class _JavascriptIntegerOverflowError extends Error { | |
| final Object _value; | |
| _JavascriptIntegerOverflowError(this._value); | |
| String toString() => "Javascript Integer Overflow: $_value"; | |
| } | |
| class _JavascriptCompatibilityError extends Error { | |
| final String _msg; | |
| _JavascriptCompatibilityError(this._msg); | |
| String toString() => "Javascript Compatibility Error: $_msg"; | |
| } | |