Version 2.17.0-180.0.dev

Merge commit '7eb04190690c339e113a057cce01394a08618520' into 'dev'
diff --git a/pkg/dart2js_info/README.md b/pkg/dart2js_info/README.md
index 0f59cc2..54f3a7a 100644
--- a/pkg/dart2js_info/README.md
+++ b/pkg/dart2js_info/README.md
@@ -134,6 +134,12 @@
     be JSON, backward-compatible JSON, binary, or protobuf schema (as defined in
     `info.proto`).
 
+  * [`runtime_coverage`][runtime_coverage]:
+    dart2js has an experimental feature to gather runtime coverage data of your
+    application. This tool correlates that with the info file and can output a
+    package-level breakdown of which files were not used during the runtime of
+    your app.
+
   * [`show`][show]: a tool that dumps info files in a readable text format.
 
 Next we describe in detail how to use each of these tools.
@@ -574,6 +580,39 @@
 $ dart2js_info runtime_coverage --show-packages main.dart.info.data main.runtime.data.txt
 ```
 
+Here's an example output snippet:
+```
+Runtime Coverage Summary
+========================================================================
+                                   bytes      %
+ Program size                   96860754 100.00%
+ Libraries (excluding statics)  94394961  97.45%
+ Code (classes + closures)      91141701  94.10%
+ Used                            3519239   3.63%
+
+                                   count      %
+ Classes + closures                15902 100.00%
+ Used                               5661  35.60%
+
+Runtime Coverage Breakdown (packages) (87622462 bytes)
+========================================================================
+ package:angular_components.material_datepicker (29881 bytes unused)
+   proportion of package used:                      43394/73275 (59.22%)
+   proportion of unused code to all code:           29881/91141701 (0.03%)
+   proportion of unused code to all unused code:    29881/87622462 (0.03%)
+   proportion of main unit code to package code:    8142/73275 (11.11%)
+   proportion of main unit code that is unused:     3088/8142 (37.93%)
+   package breakdown:
+     [-D] package:angular_components.material_datepicker/material_datepicker.dart:_ViewMaterialDatepickerComponent5: 656 bytes (0.90% of package)
+     [+D] package:angular_components.material_datepicker/calendar.dart:CalendarSelection: 645 bytes (0.88% of package)
+     [+M] package:angular_components.material_datepicker/range.dart:MonthRange: 629 bytes (0.86% of package)
+     [-M] package:angular_components.material_datepicker/range.dart:QuarterRange: 629 bytes (0.86% of package)
+...
+```
+
+A `+`/`-` indicates whether or not the element was used at runtime.
+A `M`/`D` indicates whether or not the element was in the main or deferred output unit.
+
 ## Code location, features and bugs
 
 This package is developed in [github][repo].  Please file feature requests and
@@ -592,5 +631,6 @@
 [function_size]: https://github.com/dart-lang/sdk/tree/main/pkg/dart2js_info/bin/src/function_size_analysis.dart
 [library_size]: https://github.com/dart-lang/sdk/tree/main/pkg/dart2js_info/bin/src/library_size_split.dart
 [repo]: https://github.com/dart-lang/sdk/tree/main/pkg/dart2js_info/
+[runtime_coverage]: https://github.com/dart-lang/sdk/blob/main/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
 [show]: https://github.com/dart-lang/sdk/tree/main/pkg/dart2js_info/bin/src/text_print.dart
 [tracker]: https://github.com/dart-lang/sdk/issues
diff --git a/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
index 53bb655..44429e0 100644
--- a/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
+++ b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
@@ -136,7 +136,7 @@
   var packageData = <String, PackageInfo>{};
   var unused = PriorityQueue<Info>((a, b) => b.size.compareTo(a.size));
 
-  void tallyCode(Info i) {
+  void tallyCode(BasicInfo i) {
     totalCode += i.size;
     var name = qualifiedName(i);
     var used = coverage.contains(name);
@@ -193,14 +193,31 @@
     _leftPadded('  proportion of unused code to all unused code:',
         '${packageInfo.unusedSize}/$unusedTotal ($unusedCodeRatioString%)');
 
-    _leftPadded('  package breakdown: ', '');
+    var mainUnitPackageRatioString =
+        (packageInfo.mainUnitSize / packageInfo.totalSize * 100)
+            .toStringAsFixed(2);
+    _leftPadded(
+        '  proportion of main unit code to package code:',
+        '${packageInfo.mainUnitSize}/${packageInfo.totalSize} '
+            '($mainUnitPackageRatioString%)');
+
+    var unusedMainUnitRatioString =
+        (packageInfo.unusedMainUnitSize / packageInfo.mainUnitSize * 100)
+            .toStringAsFixed(2);
+    _leftPadded(
+        '  proportion of main unit code that is unused:',
+        '${packageInfo.unusedMainUnitSize}/${packageInfo.mainUnitSize} '
+            '($unusedMainUnitRatioString%)');
+
+    print('   package breakdown:');
     for (var item in packageInfo.elements.toList()) {
       var percent =
           (item.size * 100 / packageInfo.totalSize).toStringAsFixed(2);
       var name = qualifiedName(item);
       var used = coverage.contains(name);
-      var usedNotch = used ? '+' : '-';
-      _leftPadded('    $usedNotch ${qualifiedName(item)}:',
+      var usedTick = used ? '+' : '-';
+      var mainUnitTick = item.outputUnit.name == 'main' ? 'M' : 'D';
+      _leftPadded('    [$usedTick$mainUnitTick] ${qualifiedName(item)}:',
           '${item.size} bytes ($percent% of package)');
     }
 
@@ -231,21 +248,30 @@
 }
 
 class PackageInfo {
-  final elements = PriorityQueue<Info>((a, b) => b.size.compareTo(a.size));
+  final elements = PriorityQueue<BasicInfo>((a, b) => b.size.compareTo(a.size));
+
+  num mainUnitSize = 0;
   num totalSize = 0;
-  num usedSize = 0;
+  num unusedMainUnitSize = 0;
   num unusedSize = 0;
-  num usedRatio = 0.0;
+  num usedRatio = 0;
+  num usedSize = 0;
 
   PackageInfo();
 
-  void add(Info i, {bool used = true}) {
+  void add(BasicInfo i, {bool used = true}) {
     totalSize += i.size;
     if (used) {
       usedSize += i.size;
     } else {
       unusedSize += i.size;
     }
+    if (i.outputUnit.name == 'main') {
+      mainUnitSize += i.size;
+      if (!used) {
+        unusedMainUnitSize += i.size;
+      }
+    }
     elements.add(i);
     usedRatio = usedSize / totalSize;
   }
diff --git a/pkg/dart2js_info/lib/src/util.dart b/pkg/dart2js_info/lib/src/util.dart
index 45a10d3..c90b09f 100644
--- a/pkg/dart2js_info/lib/src/util.dart
+++ b/pkg/dart2js_info/lib/src/util.dart
@@ -136,7 +136,7 @@
       return '${info.uri}'.split('/').first;
     }
     if (info.uri.isScheme('dart')) {
-      return 'dart:${info.uri.path}';
+      return '${info.uri}';
     }
     if (info.uri.hasScheme) {
       return info.uri.scheme;
diff --git a/tools/VERSION b/tools/VERSION
index 5acb79f..b27473d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 179
+PRERELEASE 180
 PRERELEASE_PATCH 0
\ No newline at end of file