Garbage-collect compiled libraries

If - for instance - a file (say 'main.dart') tries to include a part
(say 'lib.dart') that is not part of that file (i.e. doesn't state
something like 'part of "main.dart"'), and the file ('lib.dart') is not
otherwise used, before this change, the library ('lib.dart') would be
included in the first comile, but on subsequent re-compiles wouldn't
include it because it's not referenced, nor ever cleaned up
(and would thus be re-compiled.)

This change garbage-collects the library as it's not referenced.

Change-Id: I8fa90b3ae6fc3d99af9fec780abe62855e653ddb
Reviewed-on: https://dart-review.googlesource.com/c/90385
Reviewed-by: Peter von der Ahé <ahe@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 795a5d9..220f440 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -276,9 +276,9 @@
         outputLibraries = computeTransitiveClosure(compiledLibraries,
             mainMethod, entryPoint, reusedLibraries, hierarchy);
       } else {
+        outputLibraries = new List<Library>();
         computeTransitiveClosure(compiledLibraries, mainMethod, entryPoint,
-            reusedLibraries, hierarchy);
-        outputLibraries = compiledLibraries;
+            reusedLibraries, hierarchy, outputLibraries);
       }
 
       if (componentWithDill == null) {
@@ -299,19 +299,28 @@
       Procedure mainMethod,
       Uri entry,
       List<LibraryBuilder> reusedLibraries,
-      ClassHierarchy hierarchy) {
-    List<Library> result = new List<Library>.from(inputLibraries);
+      ClassHierarchy hierarchy,
+      [List<Library> inputLibrariesFiltered]) {
+    List<Library> result = new List<Library>();
     Map<Uri, Library> libraryMap = <Uri, Library>{};
+    Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
+    Map<Uri, Library> potentiallyReferencedInputLibraries = <Uri, Library>{};
     for (Library library in inputLibraries) {
       libraryMap[library.importUri] = library;
-    }
-    List<Uri> worklist = new List<Uri>.from(libraryMap.keys);
-    worklist.add(mainMethod?.enclosingLibrary?.importUri);
-    if (entry != null) {
-      worklist.add(entry);
+      if (library.importUri.scheme == "dart") {
+        result.add(library);
+        inputLibrariesFiltered?.add(library);
+      } else {
+        potentiallyReferencedLibraries[library.importUri] = library;
+        potentiallyReferencedInputLibraries[library.importUri] = library;
+      }
     }
 
-    Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
+    List<Uri> worklist = new List<Uri>();
+    Uri mainMethodUri = mainMethod?.enclosingLibrary?.importUri;
+    if (mainMethodUri != null) worklist.add(mainMethodUri);
+    if (entry != null) worklist.add(entry);
+
     for (LibraryBuilder library in reusedLibraries) {
       if (library.uri.scheme == "dart") continue;
       Library lib = library.target;
@@ -330,6 +339,9 @@
         Library library = potentiallyReferencedLibraries.remove(uri);
         if (library != null) {
           result.add(library);
+          if (potentiallyReferencedInputLibraries.remove(uri) != null) {
+            inputLibrariesFiltered?.add(library);
+          }
         }
       }
     }
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_full.status b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
index abce6e7..acb1629 100644
--- a/pkg/front_end/testcases/incremental_bulk_compiler_full.status
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
@@ -1,8 +1,3 @@
 # Copyright (c) 2018, 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.md file.
-language_2/internal_library_test: Crash # non-identical '#errors'
-language_2/missing_part_of_tag_test: Crash # missing empty library that shouldn't have been there in the first place
-language_2/part_refers_to_core_library_test: Crash # non-identical '#errors'
-language_2/script1_negative_test: Crash # missing empty library that shouldn't have been there in the first place
-language_2/script2_negative_test: Crash # missing empty library that shouldn't have been there in the first place
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
index f47d8ec..acb1629 100644
--- a/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
@@ -1,6 +1,3 @@
 # Copyright (c) 2018, 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.md file.
-language_2/missing_part_of_tag_test: Crash # missing empty library that shouldn't have been there in the first place
-language_2/script1_negative_test: Crash # missing empty library that shouldn't have been there in the first place
-language_2/script2_negative_test: Crash # missing empty library that shouldn't have been there in the first place