| Index: runtime/vm/exceptions.cc
|
| diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
|
| index 84ca37720496f8442425588e4c5d245e21ce67ea..e55edd09ed81a978509aac840f7d5169a903a741 100644
|
| --- a/runtime/vm/exceptions.cc
|
| +++ b/runtime/vm/exceptions.cc
|
| @@ -10,6 +10,7 @@
|
| #include "vm/dart_entry.h"
|
| #include "vm/debugger.h"
|
| #include "vm/flags.h"
|
| +#include "vm/log.h"
|
| #include "vm/object.h"
|
| #include "vm/object_store.h"
|
| #include "vm/stack_frame.h"
|
| @@ -23,9 +24,6 @@ DEFINE_FLAG(bool, print_stacktrace_at_throw, false,
|
| "Prints a stack trace everytime a throw occurs.");
|
|
|
|
|
| -const char* Exceptions::kCastErrorDstName = "type cast";
|
| -
|
| -
|
| class StacktraceBuilder : public ValueObject {
|
| public:
|
| StacktraceBuilder() { }
|
| @@ -371,8 +369,8 @@ static void ThrowExceptionHelper(Thread* thread,
|
| ASSERT(handler_pc != 0);
|
|
|
| if (FLAG_print_stacktrace_at_throw) {
|
| - OS::Print("Exception '%s' thrown:\n", exception.ToCString());
|
| - OS::Print("%s\n", stacktrace.ToCString());
|
| + THR_Print("Exception '%s' thrown:\n", exception.ToCString());
|
| + THR_Print("%s\n", stacktrace.ToCString());
|
| }
|
| if (handler_exists) {
|
| // Found a dart handler for the exception, jump to it.
|
| @@ -434,18 +432,20 @@ RawInstance* Exceptions::NewInstance(const char* class_name) {
|
| // Allocate, initialize, and throw a TypeError or CastError.
|
| // If error_msg is not null, throw a TypeError, even for a type cast.
|
| void Exceptions::CreateAndThrowTypeError(TokenPosition location,
|
| - const String& src_type_name,
|
| - const String& dst_type_name,
|
| + const AbstractType& src_type,
|
| + const AbstractType& dst_type,
|
| const String& dst_name,
|
| - const String& error_msg) {
|
| - const Array& args = Array::Handle(Array::New(7));
|
| + const String& bound_error_msg) {
|
| + ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead.
|
| + Zone* zone = Thread::Current()->zone();
|
| + const Array& args = Array::Handle(zone, Array::New(4));
|
|
|
| ExceptionType exception_type =
|
| - (error_msg.IsNull() && dst_name.Equals(kCastErrorDstName)) ?
|
| - kCast : kType;
|
| + (bound_error_msg.IsNull() &&
|
| + (dst_name.raw() == Symbols::InTypeCast().raw())) ? kCast : kType;
|
|
|
| DartFrameIterator iterator;
|
| - const Script& script = Script::Handle(GetCallerScript(&iterator));
|
| + const Script& script = Script::Handle(zone, GetCallerScript(&iterator));
|
| intptr_t line;
|
| intptr_t column = -1;
|
| if (script.HasSource()) {
|
| @@ -454,32 +454,64 @@ void Exceptions::CreateAndThrowTypeError(TokenPosition location,
|
| script.GetTokenLocation(location, &line, NULL);
|
| }
|
| // Initialize '_url', '_line', and '_column' arguments.
|
| - args.SetAt(0, String::Handle(script.url()));
|
| - args.SetAt(1, Smi::Handle(Smi::New(line)));
|
| - args.SetAt(2, Smi::Handle(Smi::New(column)));
|
| + args.SetAt(0, String::Handle(zone, script.url()));
|
| + args.SetAt(1, Smi::Handle(zone, Smi::New(line)));
|
| + args.SetAt(2, Smi::Handle(zone, Smi::New(column)));
|
| +
|
| + // Construct '_errorMsg'.
|
| + GrowableHandlePtrArray<const String> pieces(zone, 20);
|
|
|
| - // Initialize '_srcType', '_dstType', '_dstName', and '_errorMsg'.
|
| - args.SetAt(3, src_type_name);
|
| - args.SetAt(4, dst_type_name);
|
| - args.SetAt(5, dst_name);
|
| - args.SetAt(6, error_msg);
|
| + // Print bound error first, if any.
|
| + if (!bound_error_msg.IsNull() && (bound_error_msg.Length() > 0)) {
|
| + pieces.Add(bound_error_msg);
|
| + pieces.Add(Symbols::NewLine());
|
| + }
|
| +
|
| + // If dst_type is malformed or malbounded, only print the embedded error.
|
| + if (!dst_type.IsNull()) {
|
| + const LanguageError& error = LanguageError::Handle(zone, dst_type.error());
|
| + if (!error.IsNull()) {
|
| + // Print the embedded error only.
|
| + pieces.Add(String::Handle(zone, Symbols::New(error.ToErrorCString())));
|
| + pieces.Add(Symbols::NewLine());
|
| + } else {
|
| + // Describe the type error.
|
| + if (!src_type.IsNull()) {
|
| + pieces.Add(Symbols::TypeQuote());
|
| + pieces.Add(String::Handle(zone, src_type.UserVisibleName()));
|
| + pieces.Add(Symbols::QuoteIsNotASubtypeOf());
|
| + }
|
| + pieces.Add(Symbols::TypeQuote());
|
| + pieces.Add(String::Handle(zone, dst_type.UserVisibleName()));
|
| + pieces.Add(Symbols::SingleQuote());
|
| + if (exception_type == kCast) {
|
| + pieces.Add(dst_name);
|
| + } else if (dst_name.Length() > 0) {
|
| + pieces.Add(Symbols::SpaceOfSpace());
|
| + pieces.Add(Symbols::SingleQuote());
|
| + pieces.Add(dst_name);
|
| + pieces.Add(Symbols::SingleQuote());
|
| + }
|
| + // Print URIs of src and dst types.
|
| + pieces.Add(Symbols::SpaceWhereNewLine());
|
| + if (!src_type.IsNull()) {
|
| + pieces.Add(String::Handle(zone, src_type.EnumerateURIs()));
|
| + }
|
| + if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
|
| + pieces.Add(String::Handle(zone, dst_type.EnumerateURIs()));
|
| + }
|
| + }
|
| + }
|
| + const String& error_msg =
|
| + String::Handle(zone, Symbols::FromConcatAll(pieces));
|
| + args.SetAt(3, error_msg);
|
|
|
| // Type errors in the core library may be difficult to diagnose.
|
| // Print type error information before throwing the error when debugging.
|
| if (FLAG_print_stacktrace_at_throw) {
|
| - if (!error_msg.IsNull()) {
|
| - OS::Print("%s\n", error_msg.ToCString());
|
| - }
|
| - OS::Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ",
|
| - String::Handle(script.url()).ToCString(), line, column);
|
| - if (!dst_name.IsNull() && (dst_name.Length() > 0)) {
|
| - OS::Print("type '%s' is not a subtype of type '%s' of '%s'.\n",
|
| - src_type_name.ToCString(),
|
| - dst_type_name.ToCString(),
|
| - dst_name.ToCString());
|
| - } else {
|
| - OS::Print("type error.\n");
|
| - }
|
| + THR_Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ",
|
| + String::Handle(zone, script.url()).ToCString(), line, column);
|
| + THR_Print("%s\n", error_msg.ToCString());
|
| }
|
|
|
| // Throw TypeError or CastError instance.
|
|
|