Index: runtime/vm/exceptions.cc |
=================================================================== |
--- runtime/vm/exceptions.cc (revision 35921) |
+++ runtime/vm/exceptions.cc (working copy) |
@@ -4,6 +4,7 @@ |
#include "vm/exceptions.h" |
+#include "vm/code_patcher.h" |
#include "vm/dart_api_impl.h" |
#include "vm/dart_entry.h" |
#include "vm/debugger.h" |
@@ -34,7 +35,13 @@ |
"Prints a stack trace everytime a throw occurs."); |
DEFINE_FLAG(bool, verbose_stacktrace, false, |
"Stack traces will include methods marked invisible."); |
+DEFINE_FLAG(int, stacktrace_depth_on_warning, 5, |
+ "Maximal number of stack frames to print after a runtime warning."); |
+DECLARE_FLAG(bool, silent_warnings); |
+DECLARE_FLAG(bool, warning_as_error); |
+DECLARE_FLAG(bool, warn_on_javascript_incompatibility); |
+ |
const char* Exceptions::kCastErrorDstName = "type cast"; |
@@ -689,6 +696,10 @@ |
library = Library::CoreLibrary(); |
class_name = &Symbols::JavascriptIntegerOverflowError(); |
break; |
+ case kJavascriptCompatibilityError: |
+ library = Library::CoreLibrary(); |
+ class_name = &Symbols::JavascriptCompatibilityError(); |
+ break; |
case kAssertion: |
library = Library::CoreLibrary(); |
class_name = &Symbols::AssertionError(); |
@@ -726,4 +737,83 @@ |
arguments); |
} |
+ |
+// Throw JavascriptCompatibilityError exception. |
+static void ThrowJavascriptCompatibilityError(const char* msg) { |
+ const Array& exc_args = Array::Handle(Array::New(1)); |
+ const String& msg_str = String::Handle(String::New(msg)); |
+ exc_args.SetAt(0, msg_str); |
+ Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args); |
+} |
+ |
+ |
+bool Exceptions::MayIssueJSWarning(const ICData& ic_data, bool check_issued) { |
+ if (check_issued && ic_data.IssuedJSWarning()) { |
+ return false; |
+ } |
+ const String& target_name = String::Handle(ic_data.target_name()); |
+ if (target_name.Equals(Library::PrivateCoreLibName(Symbols::_instanceOf())) || |
+ target_name.Equals(Library::PrivateCoreLibName(Symbols::_as())) || |
+ target_name.Equals(Symbols::toString())) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+void Exceptions::JSWarning(const ICData& ic_data, const char* format, ...) { |
srdjan
2014/05/08 18:11:05
Try always passing ICData and do the necessary cod
regis
2014/05/09 21:03:42
Done.
|
+ ASSERT(FLAG_warn_on_javascript_incompatibility); |
+ if (FLAG_silent_warnings) return; |
+ if (!ic_data.IsNull()) { |
+ // Report warning only if not already reported at this location. |
+ if (ic_data.IssuedJSWarning()) { |
+ // Warning was already reported at this location. |
+ return; |
+ } |
+ ic_data.SetIssuedJSWarning(); |
+ } |
+ DartFrameIterator iterator; |
+ if (ic_data.IsNull()) { |
+ iterator.NextFrame(); // Skip native call. |
+ } |
+ StackFrame* caller_frame = iterator.NextFrame(); |
+ ASSERT(caller_frame != NULL); |
+ const Code& caller_code = Code::Handle(caller_frame->LookupDartCode()); |
+ ASSERT(!caller_code.IsNull()); |
+ const uword caller_pc = caller_frame->pc(); |
+ if (ic_data.IsNull()) { |
+ // Assume an instance call. |
+ ICData& inst_call_ic_data = ICData::Handle(); |
+ CodePatcher::GetInstanceCallAt(caller_pc, caller_code, &inst_call_ic_data); |
+ ASSERT(!inst_call_ic_data.IsNull()); |
+ // Report warning only if not already reported at this location. |
+ if (inst_call_ic_data.IssuedJSWarning()) { |
+ // Warning was already reported at this location. |
+ return; |
+ } |
+ inst_call_ic_data.SetIssuedJSWarning(); |
+ } |
+ const intptr_t token_pos = caller_code.GetTokenIndexOfPC(caller_pc); |
+ const Function& caller = Function::Handle(caller_code.function()); |
+ const Script& script = Script::Handle(caller.script()); |
+ va_list args; |
+ va_start(args, format); |
+ const Error& error = Error::Handle( |
+ LanguageError::NewFormattedV(Error::Handle(), // No previous error. |
+ script, token_pos, LanguageError::kWarning, |
+ Heap::kNew, format, args)); |
+ va_end(args); |
+ if (FLAG_warning_as_error) { |
+ ThrowJavascriptCompatibilityError(error.ToErrorCString()); |
+ } else { |
+ OS::Print("%s", error.ToErrorCString()); |
+ } |
+ const Stacktrace& stacktrace = |
+ Stacktrace::Handle(Exceptions::CurrentStacktrace()); |
+ intptr_t idx = 0; |
+ OS::Print("%s", |
+ stacktrace.ToCStringInternal(&idx, |
+ FLAG_stacktrace_depth_on_warning)); |
+} |
+ |
} // namespace dart |