[vm/kernel] Reformat uris of core-library scripts when reporting exceptions.

Currently front-end embeds absolute paths to build time locations into
Kernel binaries. Reporting those to user make stack trace unreadable and
also breaks stack trace filters that attempt to filter out implementation
frames from dart:async:

#1      _RootZone.runUnary (file:///Users/vegorov/src/dart/sdk/sdk/lib/async/zone.dart:1381:54)

same frame in legacy mode looks like this:

#1      _RootZone.runUnary (dart:async/zone.dart:1381)

This CL changes stack frame formatting so that even in Dart 2 mode result looks
closer to legacy mode result.

This is a workaround for https://github.com/dart-lang/sdk/issues/32087

Change-Id: Ic69cb039ff7d40d0e8e5340a9c1dc067427479ea
Reviewed-on: https://dart-review.googlesource.com/40522
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 21580bd..840ca2f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -22574,15 +22574,45 @@
       }
     }
   }
+
+  // Workaround for http://dartbug.com/32087: currently Kernel front-end
+  // embeds absolute build-time paths to core library sources into Kernel
+  // binaries this introduces discrepancy between how stack traces were
+  // looked like in legacy pipeline and how they look in Dart 2 pipeline and
+  // breaks users' code that attempts to pattern match and filter various
+  // irrelevant frames (e.g. frames from dart:async).
+  // To work around this issue we reformat urls of scripts belonging to
+  // dart:-scheme libraries to look like they looked like in legacy pipeline:
+  //
+  //               dart:libname/filename.dart
+  //
+  const char* url_string = url.ToCString();
+  if (script.kernel_program_info() != KernelProgramInfo::null()) {
+    const Class& owner = Class::Handle(function.Owner());
+    const Library& lib = Library::Handle(owner.library());
+    if (lib.is_dart_scheme()) {
+      // Search backwards until '/' is found. That gives us the filename.
+      intptr_t pos = strlen(url_string) - 1;
+      while (pos >= 0 && url_string[pos] != '/') {
+        pos--;
+      }
+      const char* filename = url_string + (pos + 1);
+
+      // Glue together canonic library url (e.g. dart:async) and filename.
+      url_string = zone->PrintToString(
+          "%s/%s", String::Handle(lib.url()).ToCString(), filename);
+    }
+  }
+
   if (column >= 0) {
     buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index,
-                   function_name.ToCString(), url.ToCString(), line, column);
+                   function_name.ToCString(), url_string, line, column);
   } else if (line >= 0) {
     buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index,
-                   function_name.ToCString(), url.ToCString(), line);
+                   function_name.ToCString(), url_string, line);
   } else {
     buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index,
-                   function_name.ToCString(), url.ToCString());
+                   function_name.ToCString(), url_string);
   }
 }