Version 2.17.0-204.0.dev

Merge commit 'a40f7d2a42ed3c4691fe5b6aed1331f4f234531b' into 'dev'
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b38dc18..a9e3ca4 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -777,10 +777,17 @@
   if (is_win) {
     # The only difference on windows is that the inlining is less aggressive.
     # (We accept the default level). Otherwise it is very slow.
-    cflags = [
-      "/O${debug_optimization_level}",  # Do some optimizations.
-      "/Oy-",  # Disable omitting frame pointers, must be after /O2.
-    ]
+    if (is_clang && debug_optimization_level != "2") {
+      cflags = [
+        "-d${debug_optimization_level}",  # Do some optimizations.
+        "/Oy-",  # Disable omitting frame pointers, must be after /O2.
+      ]
+    } else {
+      cflags = [
+        "/O${debug_optimization_level}",  # Do some optimizations.
+        "/Oy-",  # Disable omitting frame pointers, must be after /O2.
+      ]
+    }
   } else if (is_android) {
     # On Android we kind of optimize some things that don't affect debugging
     # much even when optimization is disabled to get the binary size down.
diff --git a/pkg/front_end/tool/fasta.dart b/pkg/front_end/tool/fasta.dart
index cdd5609..20ed126 100644
--- a/pkg/front_end/tool/fasta.dart
+++ b/pkg/front_end/tool/fasta.dart
@@ -106,7 +106,7 @@
       stop("'$command' isn't a valid subcommand.");
   }
 
-  if (extraVmArguments.isNotEmpty) {
+  if (extraVmArguments.isNotEmpty || !assertsEnabled) {
     List<String> arguments = [];
     arguments.addAll(extraVmArguments);
     arguments.add('--enable-asserts');
@@ -124,7 +124,7 @@
     arguments.addAll(remainingArguments);
     arguments.addAll(scriptArguments);
 
-    print('Running: ${script} ${arguments.join(' ')}');
+    print('Calling: ${script} ${arguments.join(' ')}');
     await mainFunction(arguments);
   }
 }
@@ -133,3 +133,12 @@
   stderr.write(message);
   exit(2);
 }
+
+final bool assertsEnabled = () {
+  try {
+    assert(false);
+    return false;
+  } catch (_) {
+    return true;
+  }
+}();
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
index 6b5f9b2..762b17e 100644
--- a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -37,9 +37,16 @@
           metadata.protectedNames.add(name + "=");
         }
         final parent = node.parent;
+        final Library library;
         if (parent is Class) {
           metadata.protectedNames.add(parent.name);
+          library = parent.enclosingLibrary;
+        } else if (parent is Library) {
+          library = parent;
+        } else {
+          throw "Unexpected parent";
         }
+        metadata.protectedNames.add(library.importUri.toString());
         break;
       }
     }
diff --git a/pkg/vm/test/obfuscation_test.dart b/pkg/vm/test/obfuscation_test.dart
new file mode 100644
index 0000000..8ee7401
--- /dev/null
+++ b/pkg/vm/test/obfuscation_test.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2022, 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 file.
+
+import 'dart:convert';
+import "dart:io";
+
+import 'package:front_end/src/api_unstable/vm.dart'
+    show computePlatformBinariesLocation;
+
+main() {
+  final Directory tmpDir =
+      Directory.systemTemp.createTempSync("obfuscationtest");
+  try {
+    final Uri tmpDirUri = tmpDir.uri;
+    final Uri secretfilename = tmpDirUri.resolve("secretfilename.dart");
+    final File secretfilenameFile = new File.fromUri(secretfilename);
+    secretfilenameFile.writeAsStringSync("""
+import "secretfilename2.dart";
+
+main() {
+  print("Hello, World!");
+  verySecretFoo();
+}
+""");
+    final Uri secretfilename2 = tmpDirUri.resolve("secretfilename2.dart");
+    final File secretfilename2File = new File.fromUri(secretfilename2);
+    secretfilename2File.writeAsStringSync("""
+@pragma('vm:entry-point')
+void verySecretFoo() {
+  print("foo!");
+  alsoVerySecretFoo();
+}
+
+void alsoVerySecretFoo() {
+  print("foo too!");
+}
+""");
+
+    List<MappingPair> mapping = getSnapshotMap(tmpDir, secretfilenameFile);
+    bool good = verify(mapping, {
+      // This contains @pragma('vm:entry-point') and the uri should not change.
+      secretfilename2.toString(),
+      // This contains @pragma('vm:entry-point') and the name should not change.
+      "verySecretFoo",
+    }, {
+      // This is not special and should have been obfuscated.
+      secretfilename.toString(),
+      // This is not special and should have been obfuscated.
+      "alsoVerySecretFoo"
+    });
+    if (!good) throw "Obfuscation didn't work as expected";
+    print("Good");
+  } finally {
+    tmpDir.deleteSync(recursive: true);
+  }
+}
+
+List<MappingPair> getSnapshotMap(Directory tmpDir, File compileDartFile) {
+  final Uri genKernel = Platform.script.resolve('../bin/gen_kernel.dart');
+  final File genKernelFile = new File.fromUri(genKernel);
+  if (!genKernelFile.existsSync()) {
+    throw "Didn't find gen_kernel at $genKernel";
+  }
+
+  File resolvedExecutableFile = new File(Platform.resolvedExecutable);
+  Uri resolvedExecutable = resolvedExecutableFile.uri;
+  String genSnapshotFilename = "gen_snapshot";
+  if (Platform.isWindows) genSnapshotFilename += ".exe";
+
+  Uri genSnapshot = resolvedExecutable.resolve(genSnapshotFilename);
+  File genSnapshotFile = new File.fromUri(genSnapshot);
+  if (!genSnapshotFile.existsSync()) {
+    print(
+        "Didn't find gen_kernel at $genSnapshot... Trying utils/$genSnapshotFilename");
+    genSnapshot = resolvedExecutable.resolve("utils/$genSnapshotFilename");
+    genSnapshotFile = new File.fromUri(genSnapshot);
+    if (!genSnapshotFile.existsSync()) {
+      throw "Didn't find gen_kernel at $genSnapshot";
+    }
+  }
+
+  final Uri platformDill = computePlatformBinariesLocation()
+      .resolve('vm_platform_strong_product.dill');
+  final File platformDillFile = new File.fromUri(platformDill);
+  if (!platformDillFile.existsSync()) {
+    throw "Didn't find vm_platform_strong_product at $platformDill";
+  }
+
+  final Uri tmpDirUri = tmpDir.uri;
+
+  final Uri kernelDill = tmpDirUri.resolve("kernel.dill");
+  final File kernelDillFile = new File.fromUri(kernelDill);
+
+  print("Running gen_kernel");
+  // Extracted from pkg/dart2native/lib/dart2native.dart.
+  final ProcessResult kernelRun = Process.runSync(Platform.resolvedExecutable, [
+    genKernelFile.path,
+    "--platform",
+    platformDillFile.path,
+    "--aot",
+    "-Ddart.vm.product=true",
+    "-o",
+    kernelDillFile.path,
+    "--invocation-modes=compile",
+    "--verbosity=all",
+    compileDartFile.path
+  ]);
+
+  if (kernelRun.exitCode != 0) {
+    throw "Got exit code ${kernelRun.exitCode}\n"
+        "stdout: ${kernelRun.stdout}\n"
+        "stderr: ${kernelRun.stderr}";
+  }
+
+  final Uri aotElf = tmpDirUri.resolve("aot.elf");
+  final File aotElfFile = new File.fromUri(aotElf);
+  final Uri obfuscationMap = tmpDirUri.resolve("obfuscation.map");
+  final File obfuscationMapFile = new File.fromUri(obfuscationMap);
+
+  print("Running $genSnapshot");
+  // Extracted from pkg/dart2native/lib/dart2native.dart.
+  final ProcessResult snapshotRun = Process.runSync(genSnapshotFile.path, [
+    "--snapshot-kind=app-aot-elf",
+    "--elf=${aotElfFile.path}",
+    "--dwarf-stack-traces",
+    "--obfuscate",
+    "--strip",
+    "--save-obfuscation-map=${obfuscationMapFile.path}",
+    kernelDillFile.path,
+  ]);
+
+  if (snapshotRun.exitCode != 0) {
+    throw "Got exit code ${snapshotRun.exitCode}\n"
+        "stdout: ${snapshotRun.stdout}\n"
+        "stderr: ${snapshotRun.stderr}";
+  }
+
+  print("Reading $obfuscationMap");
+
+  return readJsonMapping(obfuscationMapFile);
+}
+
+List<MappingPair> readJsonMapping(File file) {
+  List<MappingPair> result = [];
+  List<dynamic> json = jsonDecode(file.readAsStringSync());
+  for (int i = 0; i < json.length; i += 2) {
+    result.add(new MappingPair(json[i] as String, json[i + 1] as String));
+  }
+  return result;
+}
+
+class MappingPair {
+  final String from;
+  final String to;
+
+  MappingPair(this.from, this.to);
+
+  String toString() => "MappingPair[$from->$to]";
+}
+
+bool verify(List<MappingPair> mapping, Set<String> expectedIdentity,
+    Set<String> expectedDifferent) {
+  bool good = true;
+  Set<String> missingKeys = new Set<String>.of(expectedIdentity)
+    ..addAll(expectedDifferent);
+  for (MappingPair entry in mapping) {
+    missingKeys.remove(entry.from);
+    if (expectedIdentity.contains(entry.from) && entry.from != entry.to) {
+      print("Expected ${entry.from} to map to itself, "
+          "but mapped to ${entry.to}");
+      good = false;
+    }
+    if (expectedDifferent.contains(entry.from) && entry.from == entry.to) {
+      print("Expected ${entry.from} to map to something different, "
+          "but it didn't.");
+      good = false;
+    }
+  }
+  if (missingKeys.isNotEmpty) {
+    print("Expected to have seen the following entries which wasn't found:");
+    for (String missingKey in missingKeys) {
+      print("- $missingKey");
+    }
+    good = false;
+  }
+  return good;
+}
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 12d3dfb..2cce01c 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -168,10 +168,17 @@
   # flags.
   if (is_win) {
     if (dart_debug) {
-      cflags = [
-        "/O${dart_debug_optimization_level}",
-        "/Oy-",
-      ]
+      if (is_clang && dart_debug_optimization_level != "2") {
+        cflags = [
+          "-d${dart_debug_optimization_level}",
+          "/Oy-",
+        ]
+      } else {
+        cflags = [
+          "/O${dart_debug_optimization_level}",
+          "/Oy-",
+        ]
+      }
     } else {
       cflags = [
         "/O2",
diff --git a/tools/VERSION b/tools/VERSION
index 18b3435..8c45d2b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 203
+PRERELEASE 204
 PRERELEASE_PATCH 0
\ No newline at end of file