From 53327f4a7ca2ddd20a40f6a94db61ac136371b03 Mon Sep 17 00:00:00 2001
From: Sigmund Cherem <sigmund@google.com>
Date: Fri, 27 Jan 2017 08:10:39 -0800
Subject: [PATCH] Fix URI for packages: make them self contained within the
 domain served by pub-serve

R=nweiz@google.com, rnystrom@google.com

BUG= https://github.com/dart-lang/pub/issues/1511

Review-Url: https://codereview.chromium.org//2653753010 .
---
 lib/src/barback/dart2js_transformer.dart      | 10 ++-
 .../source_maps_are_self_contained_test.dart  | 78 +++++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 test/dart2js/source_maps_are_self_contained_test.dart

diff --git a/lib/src/barback/dart2js_transformer.dart b/lib/src/barback/dart2js_transformer.dart
index 94d05d18..54428a1e 100644
--- a/lib/src/barback/dart2js_transformer.dart
+++ b/lib/src/barback/dart2js_transformer.dart
@@ -125,6 +125,14 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
 
     var entrypoint = _environment.graph.packages[id.package].path(id.path);
 
+    // We define the packageRoot in terms of the entrypoint directory, and not
+    // the rootPackage, to ensure that the generated source-maps are valid.
+    // Source-maps contain relative URLs to package sources and these relative
+    // URLs should be self-contained within the paths served by pub-serve.
+    // See #1511 for details.
+    var buildDir = _environment.getSourceDirectoryContaining(id.path);
+    var packageRoot = _environment.rootPackage.path(buildDir, "packages");
+
     // TODO(rnystrom): Should have more sophisticated error-handling here. Need
     // to report compile errors to the user in an easily visible way. Need to
     // make sure paths in errors are mapped to the original source path so they
@@ -138,7 +146,7 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
             'minify', defaultsTo: _settings.mode == BarbackMode.RELEASE),
         verbose: _configBool('verbose'),
         environment: _configEnvironment,
-        packageRoot: _environment.rootPackage.path("packages"),
+        packageRoot: packageRoot,
         analyzeAll: _configBool('analyzeAll'),
         preserveUris: _configBool('preserveUris'),
         suppressWarnings: _configBool('suppressWarnings'),
diff --git a/test/dart2js/source_maps_are_self_contained_test.dart b/test/dart2js/source_maps_are_self_contained_test.dart
new file mode 100644
index 00000000..018432e0
--- /dev/null
+++ b/test/dart2js/source_maps_are_self_contained_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  // This test is a bit shaky. Since dart2js is free to inline things, it's
+  // not precise as to which source libraries will actually be referenced in
+  // the source map. But this tries to use a type from a package and validate
+  // that its source ends up in the source map with a valid URI.
+  integration("Source maps URIs for files in packages are self-contained", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.dir("lib", [
+        d.file("foo.dart",
+            """
+            library foo;
+            foo() {
+              // As of today dart2js will not inline this code.
+              if ('\${new DateTime.now()}' == 'abc') return 1;
+              return 2;
+            }
+            """)
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      }),
+      d.dir("web", [
+        d.file("main.dart",
+            """
+            import 'package:foo/foo.dart';
+            main() => foo();
+            """),
+        d.dir("sub", [
+          d.file("main2.dart",
+            """
+            import 'package:foo/foo.dart';
+            main() => foo();
+            """),
+        ])
+      ])
+    ]).create();
+
+
+    pubGet();
+    schedulePub(args: ["build", "--mode", "debug"],
+        output: new RegExp(r'Built \d+ files to "build".'),
+        exitCode: 0);
+
+    d.dir(appPath, [
+      d.dir("build", [
+        d.dir("web", [
+          d.matcherFile("main.dart.js.map",
+              // Note: we include the quotes to ensure this is the full URL path
+              // in the source map
+              contains(r'"packages/foo/foo.dart"')),
+          d.dir("sub", [
+            d.matcherFile("main2.dart.js.map",
+                contains(r'"../packages/foo/foo.dart"'))
+          ]),
+          d.dir("packages", [
+            d.dir(r"foo", [
+              d.matcherFile("foo.dart",
+                contains("foo() {"))
+            ])
+          ])
+        ])
+      ])
+    ]).validate();
+  });
+}
-- 
GitLab