Files
sdk/runtime/lib/errors_patch.dart
T
Régis Crelier 8cf9ef22c4 Revert "Dart Core Lib change to support generic functions in class NoSuchMethodError."
This reverts commit db15f5d73b.

Dart2js and Kernel tests are comparing text that has changed because of
the core lib change.

Change-Id: I1d33716a3d6e6a077aa1f1a9ad7cc37825d31fa6
Reviewed-on: https://dart-review.googlesource.com/9082
Reviewed-by: Siva Chandra <sivachandra@google.com>
2017-09-27 21:08:20 +00:00

442 lines
14 KiB
Dart

// 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.
@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;
StackTrace _stackTrace;
}
class _AssertionError extends Error implements AssertionError {
_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.
static _throwNew(int assertionStart, int assertionEnd, Object message) {
_doThrowNew(assertionStart, assertionEnd, message);
}
static _doThrowNew(int assertionStart, int assertionEnd, Object message)
native "AssertionError_throwNew";
static _evaluateAssertion(condition) {
if (identical(condition, true) || identical(condition, false)) {
return condition;
}
if (condition is _Closure) {
return condition();
}
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 {
_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, String bound_error_msg) native "TypeError_throwNew";
static _throwNewIfNotLoaded(
_LibraryPrefix prefix,
int location,
Object src_value,
_Type dst_type,
String dst_name,
String bound_error_msg) {
if (!prefix.isLoaded()) {
_throwNew(location, src_value, dst_type, dst_name, bound_error_msg);
}
}
String toString() => super.message;
}
class _CastError extends Error implements CastError {
_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
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 {
const _InternalError(this._msg);
String toString() => "InternalError: '${_msg}'";
final String _msg;
}
@patch
class UnsupportedError {
static _throwNew(String msg) {
throw new UnsupportedError(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) {
// TODO(srdjan): Unresolvable static methods sometimes do not provide the
// arguments, because the arguments are evaluated but not passed to the
// throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and
// Parser::ThrowNoSuchMethodError)). There is no way to distinguish the
// case of no arguments from the case of the arguments not being passed
// in here, though. See https://github.com/dart-lang/sdk/issues/27572
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);
}
static void _throwNewIfNotLoaded(
_LibraryPrefix prefix,
Object receiver,
String memberName,
int invocation_type,
List arguments,
List argumentNames,
List existingArgumentNames) {
if (!prefix.isLoaded()) {
_throwNew(receiver, memberName, invocation_type, arguments, argumentNames,
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;
@patch
NoSuchMethodError(Object receiver, Symbol memberName,
List positionalArguments, Map<Symbol, dynamic> namedArguments,
[List existingArgumentNames = null])
: _receiver = receiver,
_memberName = memberName,
_arguments = positionalArguments,
_namedArguments = namedArguments,
_existingArgumentNames = existingArgumentNames,
_invocation_type = -1;
// This constructor seems to be called with either strings or
// values read from another NoSuchMethodError.
//
// NOTE: When making changes to this constructor, please also update
// `VmTarget.instantiateNoSuchMethodError` in
// `pkg/kernel/lib/target/vm.dart`.
NoSuchMethodError._withType(
this._receiver,
/*String|Symbol*/ memberName,
this._invocation_type,
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;
@patch
String toString() {
var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
_InvocationMirror._CALL_MASK;
var type = _invocation_type & _InvocationMirror._TYPE_MASK;
String memberName = (_memberName == null)
? ""
: internal.Symbol.getUnmangledName(_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.getUnmangledName(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();
}
}
class _CompileTimeError extends Error {
final String _errorMsg;
_CompileTimeError(this._errorMsg);
String toString() => _errorMsg;
}
dynamic _classRangeAssert(int position, dynamic instance, _Type type, int cid,
int lowerLimit, int upperLimit) {
if ((cid < lowerLimit || cid > upperLimit) && instance != null) {
_TypeError._throwNew(position, instance, type, " in type cast", null);
}
return instance;
}
dynamic _classIdEqualsAssert(
int position, dynamic instance, _Type type, int cid, int otherCid) {
if (cid != otherCid && instance != null) {
_TypeError._throwNew(position, instance, type, " in type cast", null);
}
return instance;
}
/// 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.";
}
@patch
class _ConstantExpressionError {
@patch
_throw(error) => throw error;
}