| // 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. |
| |
| // part of "core_patch.dart"; |
| |
| @patch |
| class Error { |
| @patch |
| static String _objectToString(Object object) { |
| return Object._toString(object); |
| } |
| |
| @patch |
| static String _stringToSafeString(String string) { |
| return json.encode(string); |
| } |
| |
| @patch |
| StackTrace get stackTrace => _stackTrace; |
| |
| @pragma("vm:entry-point") |
| StackTrace _stackTrace; |
| } |
| |
| class _AssertionError extends Error implements AssertionError { |
| @pragma("vm:entry-point") |
| _AssertionError._create( |
| this._failedAssertion, this._url, this._line, this._column, this.message); |
| |
| // AssertionError_throwNew in errors.cc fishes the assertion source code |
| // out of the script. It expects a Dart stack frame from class |
| // _AssertionError. Thus we need a Dart stub that calls the native code. |
| @pragma("vm:entry-point", "call") |
| static _throwNew(int assertionStart, int assertionEnd, Object message) { |
| _doThrowNew(assertionStart, assertionEnd, message); |
| } |
| |
| static _doThrowNew(int assertionStart, int assertionEnd, Object message) |
| native "AssertionError_throwNew"; |
| |
| @pragma("vm:entry-point", "call") |
| static _evaluateAssertion(condition) { |
| if (identical(condition, true) || identical(condition, false)) { |
| return condition; |
| } |
| if (condition is _Closure) { |
| return (condition as dynamic)(); |
| } |
| if (condition is Function) { |
| condition = condition(); |
| } |
| return condition; |
| } |
| |
| String get _messageString { |
| if (message == null) return "is not true."; |
| if (message is String) return message; |
| return Error.safeToString(message); |
| } |
| |
| String toString() { |
| if (_url == null) { |
| if (message == null) return _failedAssertion?.trim(); |
| return "'${_failedAssertion?.trim()}': $_messageString"; |
| } |
| var columnInfo = ""; |
| if (_column > 0) { |
| // Only add column information if it is valid. |
| columnInfo = " pos $_column"; |
| } |
| return "'$_url': Failed assertion: line $_line$columnInfo: " |
| "'$_failedAssertion': $_messageString"; |
| } |
| |
| final String _failedAssertion; |
| final String _url; |
| final int _line; |
| final int _column; |
| final Object message; |
| } |
| |
| class _TypeError extends _AssertionError implements TypeError { |
| @pragma("vm:entry-point") |
| _TypeError._create(String url, int line, int column, String errorMsg) |
| : super._create("is assignable", url, line, column, errorMsg); |
| |
| static _throwNew(int location, Object src_value, _Type dst_type, |
| String dst_name) native "TypeError_throwNew"; |
| |
| String toString() => super.message; |
| } |
| |
| class _CastError extends Error implements CastError { |
| @pragma("vm:entry-point") |
| _CastError._create(this._url, this._line, this._column, this._errorMsg); |
| |
| // A CastError is allocated by TypeError._throwNew() when dst_name equals |
| // Symbols::InTypeCast(). |
| |
| String toString() => _errorMsg; |
| |
| // Fields _url, _line, and _column are only used for debugging purposes. |
| final String _url; |
| final int _line; |
| final int _column; |
| final String _errorMsg; |
| } |
| |
| @patch |
| class FallThroughError { |
| @patch |
| @pragma("vm:entry-point") |
| FallThroughError._create(String url, int line) |
| : _url = url, |
| _line = 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 { |
| @pragma("vm:entry-point") |
| const _InternalError(this._msg); |
| String toString() => "InternalError: '${_msg}'"; |
| final String _msg; |
| } |
| |
| @patch |
| @pragma("vm:entry-point") |
| class UnsupportedError { |
| static _throwNew(String msg) { |
| throw new UnsupportedError(msg); |
| } |
| } |
| |
| @patch |
| class CyclicInitializationError { |
| static _throwNew(String variableName) { |
| throw new CyclicInitializationError(variableName); |
| } |
| } |
| |
| @patch |
| class AbstractClassInstantiationError { |
| @pragma("vm:entry-point") |
| 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 { |
| // Deprecated members to be removed. |
| Symbol _memberName; |
| List _arguments; |
| Map<Symbol, dynamic> _namedArguments; |
| List _existingArgumentNames; |
| |
| final Object _receiver; |
| final _InvocationMirror _invocation; |
| |
| @patch |
| NoSuchMethodError.withInvocation(Object receiver, Invocation invocation) |
| : _receiver = receiver, |
| _invocation = invocation as _InvocationMirror; |
| |
| static void _throwNewInvocation(Object receiver, Invocation invocation) { |
| throw new NoSuchMethodError.withInvocation(receiver, invocation); |
| } |
| |
| // 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. |
| @pragma("vm:entry-point", "call") |
| static void _throwNew(Object receiver, String memberName, int invocation_type, |
| Object typeArguments, List arguments, List argumentNames) { |
| throw new NoSuchMethodError._withType(receiver, memberName, invocation_type, |
| typeArguments, arguments, argumentNames); |
| } |
| |
| static void _throwNewIfNotLoaded( |
| _LibraryPrefix prefix, |
| Object receiver, |
| String memberName, |
| int invocation_type, |
| Object typeArguments, |
| List arguments, |
| List argumentNames) { |
| if (!prefix.isLoaded()) { |
| _throwNew(receiver, memberName, invocation_type, typeArguments, arguments, |
| argumentNames); |
| } |
| } |
| |
| // TODO(regis): Deprecated member still used by dart2js to be removed. |
| // 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. |
| int _invocation_type; |
| |
| // TODO(regis): Deprecated constructor still used by dart2js to be removed. |
| @patch |
| NoSuchMethodError(Object receiver, Symbol memberName, |
| List positionalArguments, Map<Symbol, dynamic> namedArguments, |
| [List existingArgumentNames = null]) |
| : _receiver = receiver, |
| _invocation = null, |
| _memberName = memberName, |
| _arguments = positionalArguments, |
| _namedArguments = namedArguments, |
| _existingArgumentNames = existingArgumentNames, |
| _invocation_type = -1; |
| |
| // Helper to build a map of named arguments. |
| static Map<Symbol, dynamic> _NamedArgumentsMap( |
| List arguments, List argumentNames) { |
| Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>(); |
| int numPositionalArguments = arguments.length - argumentNames.length; |
| for (int i = 0; i < argumentNames.length; i++) { |
| var arg_value = arguments[numPositionalArguments + i]; |
| namedArguments[new Symbol(argumentNames[i])] = arg_value; |
| } |
| return namedArguments; |
| } |
| |
| // Constructor called from Exceptions::ThrowByType(kNoSuchMethod) and from |
| // _throwNew above, taking a TypeArguments object rather than an unpacked list |
| // of types, as well as a list of all arguments and a list of names, rather |
| // than a separate list of positional arguments and a map of named arguments. |
| @pragma("vm:entry-point") |
| NoSuchMethodError._withType( |
| this._receiver, |
| String memberName, |
| int invocation_type, |
| Object typeArguments, |
| List arguments, |
| List argumentNames) |
| : this._invocation = new _InvocationMirror._withType( |
| new Symbol(memberName), |
| invocation_type, |
| typeArguments != null |
| // TODO(33073): Use actual count of type arguments in place of 0. |
| ? _InvocationMirror._unpackTypeArguments(typeArguments, 0) |
| : null, |
| argumentNames != null |
| ? arguments.sublist(0, arguments.length - argumentNames.length) |
| : arguments, |
| argumentNames != null |
| ? _NamedArgumentsMap(arguments, argumentNames) |
| : null); |
| |
| static String _existingMethodSignature(Object receiver, String methodName, |
| int invocationType) native "NoSuchMethodError_existingMethodSignature"; |
| |
| @patch |
| String toString() { |
| // TODO(regis): Remove this null check once dart2js is updated. |
| if (_invocation == null) { |
| // Use deprecated version of toString. |
| return _toStringDeprecated(); |
| } |
| String memberName = |
| internal.Symbol.computeUnmangledName(_invocation.memberName); |
| var level = (_invocation._type >> _InvocationMirror._LEVEL_SHIFT) & |
| _InvocationMirror._LEVEL_MASK; |
| var kind = _invocation._type & _InvocationMirror._KIND_MASK; |
| if (kind == _InvocationMirror._LOCAL_VAR) { |
| return "NoSuchMethodError: Cannot assign to final variable '$memberName'"; |
| } |
| |
| StringBuffer typeArgumentsBuf = null; |
| var typeArguments = _invocation.typeArguments; |
| if ((typeArguments != null) && (typeArguments.length > 0)) { |
| typeArgumentsBuf = new StringBuffer(); |
| typeArgumentsBuf.write("<"); |
| for (int i = 0; i < typeArguments.length; i++) { |
| if (i > 0) { |
| typeArgumentsBuf.write(", "); |
| } |
| typeArgumentsBuf.write(Error.safeToString(typeArguments[i])); |
| } |
| typeArgumentsBuf.write(">"); |
| } |
| StringBuffer argumentsBuf = new StringBuffer(); |
| var positionalArguments = _invocation.positionalArguments; |
| int argumentCount = 0; |
| if (positionalArguments != null) { |
| for (; argumentCount < positionalArguments.length; argumentCount++) { |
| if (argumentCount > 0) { |
| argumentsBuf.write(", "); |
| } |
| argumentsBuf |
| .write(Error.safeToString(positionalArguments[argumentCount])); |
| } |
| } |
| var namedArguments = _invocation.namedArguments; |
| if (namedArguments != null) { |
| namedArguments.forEach((Symbol key, var value) { |
| if (argumentCount > 0) { |
| argumentsBuf.write(", "); |
| } |
| argumentsBuf.write(internal.Symbol.computeUnmangledName(key)); |
| argumentsBuf.write(": "); |
| argumentsBuf.write(Error.safeToString(value)); |
| argumentCount++; |
| }); |
| } |
| String existingSig = |
| _existingMethodSignature(_receiver, memberName, _invocation._type); |
| String argsMsg = existingSig != null ? " with matching arguments" : ""; |
| |
| String kindBuf; |
| if (kind >= 0 && kind < 5) { |
| kindBuf = (const [ |
| "method", |
| "getter", |
| "setter", |
| "getter or setter", |
| "variable" |
| ])[kind]; |
| } |
| |
| StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: "); |
| bool is_type_call = false; |
| switch (level) { |
| case _InvocationMirror._DYNAMIC: |
| { |
| if (_receiver == null) { |
| if (existingSig != null) { |
| msgBuf.writeln("The null object does not have a $kindBuf " |
| "'$memberName'$argsMsg."); |
| } else { |
| msgBuf.writeln("The $kindBuf '$memberName' was called on null."); |
| } |
| } else { |
| if (_receiver is _Closure) { |
| msgBuf.writeln("Closure call with mismatched arguments: " |
| "function '$memberName'"); |
| } else if (_receiver is _Type && memberName == "call") { |
| is_type_call = true; |
| String name = _receiver.toString(); |
| msgBuf.writeln("Attempted to use type '$name' as a function. " |
| "Since types do not define a method 'call', this is not " |
| "possible. Did you intend to call the $name constructor and " |
| "forget the 'new' operator?"); |
| } else { |
| msgBuf.writeln("Class '${_receiver.runtimeType}' has no instance " |
| "$kindBuf '$memberName'$argsMsg."); |
| } |
| } |
| break; |
| } |
| case _InvocationMirror._SUPER: |
| { |
| msgBuf.writeln("Super class of class '${_receiver.runtimeType}' has " |
| "no instance $kindBuf '$memberName'$argsMsg."); |
| memberName = "super.$memberName"; |
| break; |
| } |
| case _InvocationMirror._STATIC: |
| { |
| msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg " |
| "declared in class '$_receiver'."); |
| break; |
| } |
| case _InvocationMirror._CONSTRUCTOR: |
| { |
| msgBuf.writeln("No constructor '$memberName'$argsMsg declared " |
| "in class '$_receiver'."); |
| memberName = "new $memberName"; |
| break; |
| } |
| case _InvocationMirror._TOP_LEVEL: |
| { |
| msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg " |
| "declared."); |
| break; |
| } |
| } |
| |
| if (level == _InvocationMirror._TOP_LEVEL) { |
| msgBuf.writeln("Receiver: top-level"); |
| } else { |
| msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}"); |
| } |
| |
| if (kind == _InvocationMirror._METHOD) { |
| String m = is_type_call ? "$_receiver" : "$memberName"; |
| msgBuf.write("Tried calling: $m"); |
| if (typeArgumentsBuf != null) { |
| msgBuf.write(typeArgumentsBuf); |
| } |
| msgBuf.write("($argumentsBuf)"); |
| } else if (argumentCount == 0) { |
| msgBuf.write("Tried calling: $memberName"); |
| } else if (kind == _InvocationMirror._SETTER) { |
| msgBuf.write("Tried calling: $memberName$argumentsBuf"); |
| } else { |
| msgBuf.write("Tried calling: $memberName = $argumentsBuf"); |
| } |
| |
| if (existingSig != null) { |
| msgBuf.write("\nFound: $memberName$existingSig"); |
| } |
| |
| return msgBuf.toString(); |
| } |
| |
| // TODO(regis): Remove this function once dart2js is updated. |
| String _toStringDeprecated() { |
| var level = (_invocation_type >> _InvocationMirror._LEVEL_SHIFT) & |
| _InvocationMirror._LEVEL_MASK; |
| var type = _invocation_type & _InvocationMirror._KIND_MASK; |
| String memberName = (_memberName == null) |
| ? "" |
| : internal.Symbol.computeUnmangledName(_memberName); |
| |
| if (type == _InvocationMirror._LOCAL_VAR) { |
| return "NoSuchMethodError: Cannot assign to final variable '$memberName'"; |
| } |
| |
| StringBuffer arguments = new StringBuffer(); |
| int argumentCount = 0; |
| if (_arguments != null) { |
| for (; argumentCount < _arguments.length; argumentCount++) { |
| if (argumentCount > 0) { |
| arguments.write(", "); |
| } |
| arguments.write(Error.safeToString(_arguments[argumentCount])); |
| } |
| } |
| if (_namedArguments != null) { |
| _namedArguments.forEach((Symbol key, var value) { |
| if (argumentCount > 0) { |
| arguments.write(", "); |
| } |
| arguments.write(internal.Symbol.computeUnmangledName(key)); |
| arguments.write(": "); |
| arguments.write(Error.safeToString(value)); |
| argumentCount++; |
| }); |
| } |
| bool args_mismatch = _existingArgumentNames != null; |
| String args_message = args_mismatch ? " with matching arguments" : ""; |
| |
| String type_str; |
| if (type >= 0 && type < 5) { |
| type_str = (const [ |
| "method", |
| "getter", |
| "setter", |
| "getter or setter", |
| "variable" |
| ])[type]; |
| } |
| |
| StringBuffer msg_buf = new StringBuffer("NoSuchMethodError: "); |
| bool is_type_call = false; |
| switch (level) { |
| case _InvocationMirror._DYNAMIC: |
| { |
| if (_receiver == null) { |
| if (args_mismatch) { |
| msg_buf.writeln("The null object does not have a $type_str " |
| "'$memberName'$args_message."); |
| } else { |
| msg_buf |
| .writeln("The $type_str '$memberName' was called on null."); |
| } |
| } else { |
| if (_receiver is _Closure) { |
| msg_buf.writeln("Closure call with mismatched arguments: " |
| "function '$memberName'"); |
| } else if (_receiver is _Type && memberName == "call") { |
| is_type_call = true; |
| String name = _receiver.toString(); |
| msg_buf.writeln("Attempted to use type '$name' as a function. " |
| "Since types do not define a method 'call', this is not " |
| "possible. Did you intend to call the $name constructor and " |
| "forget the 'new' operator?"); |
| } else { |
| msg_buf |
| .writeln("Class '${_receiver.runtimeType}' has no instance " |
| "$type_str '$memberName'$args_message."); |
| } |
| } |
| break; |
| } |
| case _InvocationMirror._SUPER: |
| { |
| msg_buf.writeln("Super class of class '${_receiver.runtimeType}' has " |
| "no instance $type_str '$memberName'$args_message."); |
| memberName = "super.$memberName"; |
| break; |
| } |
| case _InvocationMirror._STATIC: |
| { |
| msg_buf.writeln("No static $type_str '$memberName'$args_message " |
| "declared in class '$_receiver'."); |
| break; |
| } |
| case _InvocationMirror._CONSTRUCTOR: |
| { |
| msg_buf.writeln("No constructor '$memberName'$args_message declared " |
| "in class '$_receiver'."); |
| memberName = "new $memberName"; |
| break; |
| } |
| case _InvocationMirror._TOP_LEVEL: |
| { |
| msg_buf.writeln("No top-level $type_str '$memberName'$args_message " |
| "declared."); |
| break; |
| } |
| } |
| |
| if (level == _InvocationMirror._TOP_LEVEL) { |
| msg_buf.writeln("Receiver: top-level"); |
| } else { |
| msg_buf.writeln("Receiver: ${Error.safeToString(_receiver)}"); |
| } |
| |
| if (type == _InvocationMirror._METHOD) { |
| String m = is_type_call ? "$_receiver" : "$memberName"; |
| msg_buf.write("Tried calling: $m($arguments)"); |
| } else if (argumentCount == 0) { |
| msg_buf.write("Tried calling: $memberName"); |
| } else if (type == _InvocationMirror._SETTER) { |
| msg_buf.write("Tried calling: $memberName$arguments"); |
| } else { |
| msg_buf.write("Tried calling: $memberName = $arguments"); |
| } |
| |
| if (args_mismatch) { |
| StringBuffer formalParameters = new StringBuffer(); |
| for (int i = 0; i < _existingArgumentNames.length; i++) { |
| if (i > 0) { |
| formalParameters.write(", "); |
| } |
| formalParameters.write(_existingArgumentNames[i]); |
| } |
| msg_buf.write("\nFound: $memberName($formalParameters)"); |
| } |
| |
| return msg_buf.toString(); |
| } |
| } |
| |
| @pragma("vm:entry-point") |
| class _CompileTimeError extends Error { |
| final String _errorMsg; |
| _CompileTimeError(this._errorMsg); |
| String toString() => _errorMsg; |
| } |
| |
| /// Used by Fasta to report a runtime error when a final field with an |
| /// initializer is also initialized in a generative constructor. |
| /// |
| /// Note: in strong mode, this is a compile-time error and this class becomes |
| /// obsolete. |
| class _DuplicatedFieldInitializerError extends Error { |
| final String _name; |
| |
| _DuplicatedFieldInitializerError(this._name); |
| |
| toString() => "Error: field '$_name' is already initialized."; |
| } |