Add importUri and fileUri to Source.

This will enable the VM to map URIs to package-URIs to solve problems
such as https://github.com/dart-lang/sdk/issues/35859

Change-Id: I15520325a5b81a99a7e3f56c2e35fd775d9da946
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96905
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/compiler/lib/src/io/location_provider.dart b/pkg/compiler/lib/src/io/location_provider.dart
index 3455e31..fff55c5 100644
--- a/pkg/compiler/lib/src/io/location_provider.dart
+++ b/pkg/compiler/lib/src/io/location_provider.dart
@@ -40,7 +40,7 @@
   @override
   Location getLocation(int offset) {
     RangeError.checkValueInInterval(offset, 0, length, 'offset');
-    return new Source(lineStarts, null).getLocation(null, offset);
+    return new Source(lineStarts, null, null, null).getLocation(null, offset);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index ffdb8d0..1b358bc 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -26,9 +26,14 @@
   kernel.Source cachedKernelSource;
 
   kernel.Source get kernelSource {
-    return cachedKernelSource ??=
-        new kernel.Source(lineStarts, slowUtf8ZeroTerminatedBytes())
-          ..cachedText = slowText();
+    // TODO(johnniwinther): Instead of creating a new Source object,
+    // we should use the one provided by the front-end.
+    return cachedKernelSource ??= new kernel.Source(
+        lineStarts,
+        slowUtf8ZeroTerminatedBytes(),
+        uri /* TODO(jensj): What is the import URI? */,
+        uri)
+      ..cachedText = slowText();
   }
 
   /// The name of the file.
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 917daa3..cd0c587 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -150,7 +150,11 @@
     var uriToSource = <Uri, Source>{};
 
     void addCompilationUnit(a.CompilationUnitElement unit) {
-      uriToSource[unit.source.uri] = Source(unit.lineInfo.lineStarts, []);
+      uriToSource[unit.source.uri] = Source(
+          unit.lineInfo.lineStarts,
+          [],
+          unit.uri != null ? Uri.base.resolve(unit.uri) : unit.source.uri,
+          unit.source.uri);
     }
 
     for (var uri in bundle.unlinkedUnitUris) {
diff --git a/pkg/front_end/lib/src/compute_platform_binaries_location.dart b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
index 9ac1f54..ad98f28 100644
--- a/pkg/front_end/lib/src/compute_platform_binaries_location.dart
+++ b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
@@ -69,8 +69,11 @@
           Map<Uri, Source> uriToSource = CompilerContext.current.uriToSource;
           Source source = uriToSource[uri];
           if (source.source.isEmpty) {
-            uriToSource[uri] = new Source(source.lineStarts,
-                new File.fromUri(candidate).readAsBytesSync());
+            uriToSource[uri] = new Source(
+                source.lineStarts,
+                new File.fromUri(candidate).readAsBytesSync(),
+                source.importUri,
+                source.fileUri);
           }
         }
         return candidate;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index 4771d2c..59386d9 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
@@ -39,7 +39,7 @@
 
   @override
   void addSourceInformation(
-      Uri uri, List<int> lineStarts, List<int> sourceCode) {
+      Uri importUri, Uri fileUri, List<int> lineStarts, List<int> sourceCode) {
     unsupported("addSourceInformation", -1, null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 5473197..a8166db 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -155,8 +155,9 @@
       new SourceLoader(fileSystem, includeComments, this);
 
   void addSourceInformation(
-      Uri uri, List<int> lineStarts, List<int> sourceCode) {
-    uriToSource[uri] = new Source(lineStarts, sourceCode);
+      Uri importUri, Uri fileUri, List<int> lineStarts, List<int> sourceCode) {
+    uriToSource[fileUri] =
+        new Source(lineStarts, sourceCode, importUri, fileUri);
   }
 
   /// Return list of same size as input with possibly translated uris.
@@ -328,8 +329,10 @@
 
     Map<Uri, Source> uriToSource = new Map<Uri, Source>();
     void copySource(Uri uri, Source source) {
-      uriToSource[uri] =
-          excludeSource ? new Source(source.lineStarts, const <int>[]) : source;
+      uriToSource[uri] = excludeSource
+          ? new Source(source.lineStarts, const <int>[], source.importUri,
+              source.fileUri)
+          : source;
     }
 
     this.uriToSource.forEach(copySource);
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index ac98334..1b96164 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -60,12 +60,12 @@
 
 /// Serialize the libraries in [component] that match [filter].
 List<int> serializeComponent(Component component,
-    {bool filter(Library library), bool excludeUriToSource: false}) {
+    {bool filter(Library library), bool includeSources: true}) {
   ByteSink byteSink = new ByteSink();
-  BinaryPrinter printer = filter == null && !excludeUriToSource
-      ? new BinaryPrinter(byteSink)
+  BinaryPrinter printer = filter == null
+      ? new BinaryPrinter(byteSink, includeSources: includeSources)
       : new LimitedBinaryPrinter(
-          byteSink, filter ?? (_) => true, excludeUriToSource);
+          byteSink, filter ?? (_) => true, !includeSources);
   printer.writeComponentFile(component);
   return byteSink.builder.takeBytes();
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index ab5817c..470caa2 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -203,7 +203,11 @@
     Token token = result.tokens;
     if (!suppressLexicalErrors) {
       List<int> source = getSource(bytes);
-      target.addSourceInformation(library.fileUri, result.lineStarts, source);
+      target.addSourceInformation(
+          library.isPatch ? library.fileUri : library.uri,
+          library.fileUri,
+          result.lineStarts,
+          source);
     }
     while (token is ErrorToken) {
       if (!suppressLexicalErrors) {
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 037e74e..6e82a7d 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -131,7 +131,7 @@
   }
 
   void addSourceInformation(
-      Uri uri, List<int> lineStarts, List<int> sourceCode);
+      Uri importUri, Uri fileUri, List<int> lineStarts, List<int> sourceCode);
 
   void readPatchFiles(covariant LibraryBuilder library) {}
 
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 61d49fb..0a4fad1 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -117,7 +117,7 @@
             libraryFilter: kernelTarget.isSourceLibrary);
       }
 
-      // Copy the component to exclude the uriToSource map from the summary.
+      // Create the requested component ("truncating" or not).
       //
       // Note: we don't pass the library argument to the constructor to
       // preserve the the libraries parent pointer (it should continue to point
@@ -128,6 +128,7 @@
                 ? kernelTarget.loader.libraries
                 : summaryComponent.libraries);
       trimmedSummaryComponent.metadata.addAll(summaryComponent.metadata);
+      trimmedSummaryComponent.uriToSource.addAll(summaryComponent.uriToSource);
 
       // As documented, we only run outline transformations when we are building
       // summaries without building a full component (at this time, that's
@@ -136,7 +137,9 @@
         options.target.performOutlineTransformations(trimmedSummaryComponent);
         options.ticker.logMs("Transformed outline");
       }
-      summary = serializeComponent(trimmedSummaryComponent);
+      // Don't include source (but do add it above to include importUris).
+      summary =
+          serializeComponent(trimmedSummaryComponent, includeSources: false);
       options.ticker.logMs("Generated outline");
     }
 
diff --git a/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart b/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
index d4a75fb..8b4fe9a 100644
--- a/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
+++ b/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
@@ -91,7 +91,8 @@
     return context.context
         .runInContext<Result<TypePromotionResult>>((CompilerContext c) async {
       Uri uri = file.file.uri;
-      c.uriToSource[uri] = new Source(file.result.lineStarts, file.file.bytes);
+      c.uriToSource[uri] =
+          new Source(file.result.lineStarts, file.file.bytes, uri, uri);
       StringBuffer buffer = new StringBuffer();
       Parser parser = new Parser(new TestListener(uri, buffer));
       try {
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 613741e7..91d9ae1 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -97,6 +97,8 @@
   // Line starts are delta-encoded (they are encoded as line lengths).  The list
   // [0, 10, 25, 32, 42] is encoded as [0, 10, 15, 7, 10].
   List<UInt> lineStarts;
+
+  List<Byte> importUriUtf8Bytes;
 }
 
 type UriSource {
@@ -137,7 +139,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 21;
+  UInt32 formatVersion = 22;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2d7e3a1..44ff8e2 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -5951,9 +5951,13 @@
 
   final List<int> source;
 
+  final Uri importUri;
+
+  final Uri fileUri;
+
   String cachedText;
 
-  Source(this.lineStarts, this.source);
+  Source(this.lineStarts, this.source, this.importUri, this.fileUri);
 
   /// Return the text corresponding to [line] which is a 1-based line
   /// number. The returned line contains no line separators.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index f5b7c33..6306cef 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -696,7 +696,11 @@
         lineStarts[j] = lineStart;
         previousLineStart = lineStart;
       }
-      uriToSource[uri] = new Source(lineStarts, sourceCode);
+      List<int> importUriBytes = readByteList();
+      Uri importUri = importUriBytes.isEmpty
+          ? null
+          : Uri.parse(const Utf8Decoder().convert(importUriBytes));
+      uriToSource[uri] = new Source(lineStarts, sourceCode, importUri, uri);
     }
 
     // Read index.
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index db91bfb..a0619f6 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -740,31 +740,20 @@
     Uint8List buffer = new Uint8List(1 << 16);
     for (Uri uri in _sourceUriIndexer.index.keys) {
       index[i] = getBufferOffset();
-      Source source = ((includeSources &&
-                  _sourcesFromRealImplementation.length > i &&
-                  _sourcesFromRealImplementation[i] == true)
-              ? uriToSource[uri]
-              : null) ??
-          new Source(<int>[], const <int>[]);
-
-      String uriAsString = uri == null ? "" : "$uri";
-      if (uriAsString.length * 3 < buffer.length) {
-        int length = NotQuiteString.writeUtf8(buffer, 0, uriAsString);
-        if (length < 0) {
-          // Utf8 encoding failed.
-          writeByteList(utf8.encoder.convert(uriAsString));
-        } else {
-          writeUInt30(length);
-          for (int j = 0; j < length; j++) {
-            writeByte(buffer[j]);
-          }
-        }
-      } else {
-        // Uncommon case with very long url.
-        writeByteList(utf8.encoder.convert(uriAsString));
+      Source source = uriToSource[uri];
+      if (source == null ||
+          !(includeSources &&
+              _sourcesFromRealImplementation.length > i &&
+              _sourcesFromRealImplementation[i] == true)) {
+        source = new Source(
+            <int>[], const <int>[], source?.importUri, source?.fileUri);
       }
 
+      String uriAsString = uri == null ? "" : "$uri";
+      outputStringViaBuffer(uriAsString, buffer);
+
       writeByteList(source.source);
+
       List<int> lineStarts = source.lineStarts;
       writeUInt30(lineStarts.length);
       int previousLineStart = 0;
@@ -773,6 +762,11 @@
         writeUInt30(lineStart - previousLineStart);
         previousLineStart = lineStart;
       }
+
+      String importUriAsString =
+          source.importUri == null ? "" : "${source.importUri}";
+      outputStringViaBuffer(importUriAsString, buffer);
+
       i++;
     }
 
@@ -782,6 +776,24 @@
     }
   }
 
+  void outputStringViaBuffer(String uriAsString, Uint8List buffer) {
+    if (uriAsString.length * 3 < buffer.length) {
+      int length = NotQuiteString.writeUtf8(buffer, 0, uriAsString);
+      if (length < 0) {
+        // Utf8 encoding failed.
+        writeByteList(utf8.encoder.convert(uriAsString));
+      } else {
+        writeUInt30(length);
+        for (int j = 0; j < length; j++) {
+          writeByte(buffer[j]);
+        }
+      }
+    } else {
+      // Uncommon case with very long url.
+      writeByteList(utf8.encoder.convert(uriAsString));
+    }
+  }
+
   void writeLibraryDependencyReference(LibraryDependency node) {
     int index = _libraryDependencyIndex[node];
     if (index == null) {
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index ba6cc4e..9650fa7 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -145,7 +145,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 21;
+  static const int BinaryFormatVersion = 22;
 }
 
 abstract class ConstantTag {
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 28e92be..ab22ff4 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 
 // Both version numbers are inclusive.
 static const uint32_t kMinSupportedKernelFormatVersion = 18;
-static const uint32_t kMaxSupportedKernelFormatVersion = 21;
+static const uint32_t kMaxSupportedKernelFormatVersion = 22;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \