blob: faf342b66a1db9ba2e1dac802b1699d78182c846 [file] [log] [blame]
// 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:_internal' as internal;
import 'dart:convert' show JSON;
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);
static _throwNew(int assertionStart, int assertionEnd)
native "AssertionError_throwNew";
static void _checkAssertion(condition, int start, int end) {
if (condition is Function) {
condition = condition();
}
if (!condition) {
_throwNew(start, end);
}
}
String toString() {
if (_url == null) {
return _failedAssertion;
}
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;
}
class _TypeError extends _AssertionError implements TypeError {
_TypeError._create(String url, int line, int column, this._errorMsg)
: super._create("is assignable", url, line, column);
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() => _errorMsg;
final String _errorMsg;
}
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 {
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 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) {
// 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);
}
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;
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) ? "" : internal.Symbol.getUnmangledName(_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(internal.Symbol.getUnmangledName(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) ? "" : internal.Symbol.getUnmangledName(_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();
}
}