Support for IsolateMirror.loadUri/kImportTag.

Make file loading errors non-fatal.

Remove dependency tracking left over from the days of sky_snapshot.

Change-Id: I6852c84c44dd7074cc8a515a30468f0ba7430447
diff --git a/file_loader/file_loader.cc b/file_loader/file_loader.cc
index 4d0a23a..0acae19 100644
--- a/file_loader/file_loader.cc
+++ b/file_loader/file_loader.cc
@@ -50,6 +50,9 @@
 FileLoader::FileLoader(int dirfd) : dirfd_(dirfd) {}
 
 FileLoader::~FileLoader() {
+  for (auto kernel_buffer : kernel_buffers_)
+    free(kernel_buffer);
+
   if (dirfd_ >= 0)
     close(dirfd_);
 }
@@ -76,7 +79,6 @@
 
 bool FileLoader::LoadPackagesMap(const std::string& packages) {
   packages_ = packages;
-  dependencies_.insert(packages_);
   std::string packages_source;
   if (!ReadFileToString(packages_, &packages_source)) {
     tonic::Log("error: Unable to load .packages file '%s'.", packages_.c_str());
@@ -124,6 +126,8 @@
     return CanonicalizeURL(library, url);
   if (tag == Dart_kKernelTag)
     return Kernel(url);
+  if (tag == Dart_kImportTag)
+    return Import(url);
   return Dart_NewApiError("Unknown library tag.");
 }
 
@@ -153,25 +157,42 @@
   return url;
 }
 
-std::pair<uint8_t*, intptr_t> FileLoader::FetchBytes(const std::string& url) {
+Dart_Handle FileLoader::FetchBytes(const std::string& url,
+                                   uint8_t*& buffer,
+                                   intptr_t& buffer_size) {
+  buffer = nullptr;
+  buffer_size = -1;
+
   std::string path = filesystem::SimplifyPath(GetFilePathForURL(url));
   if (path.empty()) {
-    tonic::Log("error: Unable to read Dart source '%s'.", url.c_str());
-    PlatformExit(1);
+    std::string error_message = "error: Unable to read '" + url + "'.";
+    return Dart_NewUnhandledExceptionError(
+        Dart_NewStringFromCString(error_message.c_str()));
   }
-  auto result =
-      filesystem::ReadFileToBytes(filesystem::GetAbsoluteFilePath(path));
+  std::string absolute_path = filesystem::GetAbsoluteFilePath(path);
+  auto result = filesystem::ReadFileToBytes(absolute_path);
   if (result.first == nullptr) {
-    // TODO(aam): Same as above the file loader should not explicitly log the
-    // error or exit the process. Instead these errors should be reported to the
-    // caller of the FileLoader who can implement the application-specific error
-    // handling policy.
-    tonic::Log("error: Unable to read Dart source '%s'.", url.c_str());
-    PlatformExit(1);
+    std::string error_message =
+        "error: Unable to read '" + absolute_path + "'.";
+    return Dart_NewUnhandledExceptionError(
+        Dart_NewStringFromCString(error_message.c_str()));
   }
-  url_dependencies_.insert(url);
-  dependencies_.insert(path);
-  return result;
+  buffer = result.first;
+  buffer_size = result.second;
+  return Dart_True();
+}
+
+Dart_Handle FileLoader::Import(Dart_Handle url) {
+  std::string url_string = StdStringFromDart(url);
+  uint8_t* buffer = nullptr;
+  intptr_t buffer_size = -1;
+  Dart_Handle result = FetchBytes(url_string, buffer, buffer_size);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  // The embedder must keep the buffer alive until isolate shutdown.
+  kernel_buffers_.push_back(buffer);
+  return Dart_LoadLibraryFromKernel(buffer, buffer_size);
 }
 
 namespace {
@@ -184,11 +205,15 @@
 
 Dart_Handle FileLoader::Kernel(Dart_Handle url) {
   std::string url_string = StdStringFromDart(url);
-  std::pair<uint8_t*, intptr_t> fetched_result = FetchBytes(url_string);
-  Dart_Handle result = Dart_NewExternalTypedData(
-      Dart_TypedData_kUint8, fetched_result.first, fetched_result.second);
-  Dart_NewWeakPersistentHandle(result, fetched_result.first,
-                               fetched_result.second, MallocFinalizer);
+  uint8_t* buffer = nullptr;
+  intptr_t buffer_size = -1;
+  Dart_Handle result = FetchBytes(url_string, buffer, buffer_size);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  result =
+      Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffer, buffer_size);
+  Dart_NewWeakPersistentHandle(result, buffer, buffer_size, MallocFinalizer);
   return result;
 }
 
diff --git a/file_loader/file_loader.h b/file_loader/file_loader.h
index 41a576b..5a25058 100644
--- a/file_loader/file_loader.h
+++ b/file_loader/file_loader.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "third_party/dart/runtime/include/dart_api.h"
 #include "tonic/common/macros.h"
@@ -25,25 +26,18 @@
   // The path to the `.packages` file the packages map was loaded from.
   const std::string& packages() const { return packages_; }
 
-  // Fully resolved file paths to dependencies. For example,
-  // "package:foo/bar.dart" will be resolved to
-  // "/path/to/package/foo/lib/bar.dart".
-  const std::set<std::string>& dependencies() const { return dependencies_; }
-  // Canonicalized urls to dependencies. No package resolution is done,
-  // For example, "package:foo/bar.dart" will be "package:foo/bar.dart".
-  const std::set<std::string>& url_dependencies() const {
-    return url_dependencies_;
-  }
-
   Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
                                Dart_Handle library,
                                Dart_Handle url);
 
   Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url);
+  Dart_Handle Import(Dart_Handle url);
   Dart_Handle Kernel(Dart_Handle url);
   void SetPackagesUrl(Dart_Handle url);
 
-  std::pair<uint8_t*, intptr_t> FetchBytes(const std::string& url);
+  Dart_Handle FetchBytes(const std::string& url,
+                         uint8_t*& buffer,
+                         intptr_t& buffer_size);
 
   static const char kFileURLPrefix[];
   static const size_t kFileURLPrefixLength;
@@ -64,10 +58,9 @@
   std::pair<uint8_t*, intptr_t> ReadFileToBytes(const std::string& path);
 
   int dirfd_;
-  std::set<std::string> dependencies_;
-  std::set<std::string> url_dependencies_;
   std::string packages_;
   std::unique_ptr<PackagesMap> packages_map_;
+  std::vector<uint8_t*> kernel_buffers_;
 
   TONIC_DISALLOW_COPY_AND_ASSIGN(FileLoader);
 };