[flutter_tools] update compilation to use package config (#54467)

diff --git a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart
index 2e3a9d9..b3d935e 100644
--- a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart
+++ b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart
@@ -373,7 +373,11 @@
 
   /// Write a single file into the in-memory cache.
   void writeFile(String filePath, String contents) {
-    _files[filePath] = Uint8List.fromList(utf8.encode(contents));
+    writeBytes(filePath, utf8.encode(contents) as Uint8List);
+  }
+
+  void writeBytes(String filePath, Uint8List contents) {
+    _files[filePath] = contents;
   }
 
   /// Update the in-memory asset server with the provided source and manifest files.
@@ -620,6 +624,9 @@
   @override
   DateTime lastCompiled;
 
+  @override
+  PackageConfig lastPackageConfig;
+
   // We do not evict assets on the web.
   @override
   Set<String> get assetPathsToEvict => const <String>{};
@@ -668,7 +675,7 @@
 
   @override
   Future<UpdateFSReport> update({
-    String mainPath,
+    Uri mainUri,
     String target,
     AssetBundle bundle,
     DateTime firstBuildTime,
@@ -681,20 +688,23 @@
     String pathToReload,
     List<Uri> invalidatedFiles,
     bool skipAssets = false,
+    @required PackageConfig packageConfig,
   }) async {
     assert(trackWidgetCreation != null);
     assert(generator != null);
-    final String outputDirectoryPath = globals.fs.file(mainPath).parent.path;
+    lastPackageConfig = packageConfig;
+    final File mainFile = globals.fs.file(mainUri);
+    final String outputDirectoryPath = mainFile.parent.path;
 
     if (bundleFirstUpload) {
       webAssetServer.entrypointCacheDirectory = globals.fs.directory(outputDirectoryPath);
       generator.addFileSystemRoot(outputDirectoryPath);
-      final String entrypoint = globals.fs.path.basename(mainPath);
-      webAssetServer.writeFile(entrypoint, globals.fs.file(mainPath).readAsStringSync());
+      final String entrypoint = globals.fs.path.basename(mainFile.path);
+      webAssetServer.writeBytes(entrypoint, mainFile.readAsBytesSync());
+      webAssetServer.writeBytes('require.js', requireJS.readAsBytesSync());
+      webAssetServer.writeBytes('stack_trace_mapper.js', stackTraceMapper.readAsBytesSync());
       webAssetServer.writeFile('manifest.json', '{"info":"manifest not generated in run mode."}');
       webAssetServer.writeFile('flutter_service_worker.js', '// Service worker not loaded in run mode.');
-      webAssetServer.writeFile('require.js', requireJS.readAsStringSync());
-      webAssetServer.writeFile('stack_trace_mapper.js', stackTraceMapper.readAsStringSync());
       webAssetServer.writeFile(
         'main.dart.js',
         generateBootstrapScript(
@@ -727,11 +737,14 @@
     // mapping the file name, this is done via an additional file root and
     // specicial hard-coded scheme.
     final CompilerOutput compilerOutput = await generator.recompile(
-     'org-dartlang-app:///' + globals.fs.path.basename(mainPath),
+      Uri(
+        scheme: 'org-dartlang-app',
+        path: '/' + mainUri.pathSegments.last,
+      ),
       invalidatedFiles,
       outputPath: dillOutputPath ??
         getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
-      packagesFilePath: packagesFilePath,
+      packageConfig: packageConfig,
     );
     if (compilerOutput == null || compilerOutput.errorCount > 0) {
       return UpdateFSReport(success: false);
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index 1c3acdf..e856412 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -6,6 +6,7 @@
 
 import 'package:dwds/dwds.dart';
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 import 'package:vm_service/vm_service.dart' as vmservice;
 import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
     hide StackTrace;
@@ -21,7 +22,6 @@
 import '../base/utils.dart';
 import '../build_info.dart';
 import '../cache.dart';
-import '../compile.dart';
 import '../convert.dart';
 import '../dart/pub.dart';
 import '../devfs.dart';
@@ -558,7 +558,7 @@
   // Flutter web projects need to include a generated main entrypoint to call the
   // appropriate bootstrap method and inject plugins.
   // Keep this in sync with build_system/targets/web.dart.
-  Future<String> _generateEntrypoint(String main, String packagesPath) async {
+  Future<Uri> _generateEntrypoint(Uri mainUri, PackageConfig packageConfig) async {
     File result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
     if (_generatedEntrypointDirectory == null) {
       _generatedEntrypointDirectory ??= globals.fs.systemTempDirectory.createTempSync('flutter_tools.')
@@ -569,18 +569,20 @@
         .any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
       await injectPlugins(flutterProject, checkProjects: true);
 
-      final PackageUriMapper packageUriMapper = PackageUriMapper(main, packagesPath, null, null);
-      final String generatedPath = globals.fs.currentDirectory
+      final Uri generatedUri = globals.fs.currentDirectory
         .childDirectory('lib')
         .childFile('generated_plugin_registrant.dart')
-        .absolute.path;
-      final Uri generatedImport = packageUriMapper.map(generatedPath);
-      String importedEntrypoint = packageUriMapper.map(main)?.toString();
+        .absolute.uri;
+      final Uri generatedImport = packageConfig.toPackageUri(generatedUri);
+      Uri importedEntrypoint = packageConfig.toPackageUri(mainUri);
       // Special handling for entrypoints that are not under lib, such as test scripts.
       if (importedEntrypoint == null) {
-        final String parent = globals.fs.file(main).parent.path;
+        final String parent = globals.fs.file(mainUri).parent.path;
         flutterDevices.first.generator.addFileSystemRoot(parent);
-        importedEntrypoint = 'org-dartlang-app:///${globals.fs.path.basename(main)}';
+        importedEntrypoint = Uri(
+          scheme: 'org-dartlang-app',
+          path: '/' + mainUri.pathSegments.last,
+        );
       }
 
       final String entrypoint = <String>[
@@ -604,7 +606,7 @@
       ].join('\n');
       result.writeAsStringSync(entrypoint);
     }
-    return result.path;
+    return result.absolute.uri;
   }
 
   Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
@@ -617,18 +619,21 @@
         return UpdateFSReport(success: false);
       }
     }
-    final List<Uri> invalidatedFiles =
-        await projectFileInvalidator.findInvalidated(
+    final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
       lastCompiled: device.devFS.lastCompiled,
       urisToMonitor: device.devFS.sources,
       packagesPath: packagesFilePath,
+      packageConfig: device.devFS.lastPackageConfig,
     );
     final Status devFSStatus = globals.logger.startProgress(
       'Syncing files to device ${device.device.name}...',
       timeout: timeoutConfiguration.fastOperation,
     );
     final UpdateFSReport report = await device.devFS.update(
-      mainPath: await _generateEntrypoint(mainPath, packagesFilePath),
+      mainUri: await _generateEntrypoint(
+        globals.fs.file(mainPath).absolute.uri,
+        invalidationResult.packageConfig,
+      ),
       target: target,
       bundle: assetBundle,
       firstBuildTime: firstBuildTime,
@@ -638,7 +643,8 @@
       dillOutputPath: dillOutputPath,
       projectRootPath: projectRootPath,
       pathToReload: getReloadPath(fullRestart: fullRestart),
-      invalidatedFiles: invalidatedFiles,
+      invalidatedFiles: invalidationResult.uris,
+      packageConfig: invalidationResult.packageConfig,
       trackWidgetCreation: true,
     );
     devFSStatus.stop();
diff --git a/packages/flutter_tools/lib/src/build_system/targets/dart.dart b/packages/flutter_tools/lib/src/build_system/targets/dart.dart
index 102f63a..b7bbcd4 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/dart.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/dart.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:package_config/package_config.dart';
+
 import '../../artifacts.dart';
 import '../../base/build.dart';
 import '../../base/file_system.dart';
@@ -196,7 +198,7 @@
     }
     final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
     final String targetFile = environment.defines[kTargetFile] ?? globals.fs.path.join('lib', 'main.dart');
-    final String packagesPath = environment.projectDir.childFile('.packages').path;
+    final File packagesFile = environment.projectDir.childFile('.packages');
     final String targetFileAbsolute = globals.fs.file(targetFile).absolute.path;
     // everything besides 'false' is considered to be enabled.
     final bool trackWidgetCreation = environment.defines[kTrackWidgetCreation] != 'false';
@@ -229,6 +231,17 @@
         forceLinkPlatform = false;
     }
 
+    final PackageConfig packageConfig = await loadPackageConfigUri(
+     packagesFile.absolute.uri,
+      loader: (Uri uri) {
+        final File file = globals.fs.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
+
     final CompilerOutput output = await compiler.compile(
       sdkRoot: globals.artifacts.getArtifactPath(
         Artifact.flutterPatchedSdkPath,
@@ -240,7 +253,7 @@
       trackWidgetCreation: trackWidgetCreation && buildMode == BuildMode.debug,
       targetModel: targetModel,
       outputFilePath: environment.buildDir.childFile('app.dill').path,
-      packagesPath: packagesPath,
+      packagesPath: packagesFile.path,
       linkPlatformKernelIn: forceLinkPlatform || buildMode.isPrecompiled,
       mainPath: targetFileAbsolute,
       depFilePath: environment.buildDir.childFile('kernel_snapshot.d').path,
@@ -248,6 +261,7 @@
       fileSystemRoots: fileSystemRoots,
       fileSystemScheme: fileSystemScheme,
       dartDefines: parseDartDefines(environment),
+      packageConfig: packageConfig,
     );
     if (output == null || output.errorCount != 0) {
       throw Exception('Errors during snapshot creation: $output');
diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart
index cbaa2a0..4937bd9 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import 'package:crypto/crypto.dart';
+import 'package:package_config/package_config.dart';
 
 import '../../artifacts.dart';
 import '../../base/file_system.dart';
 import '../../base/io.dart';
 import '../../build_info.dart';
-import '../../compile.dart';
 import '../../dart/package_map.dart';
 import '../../globals.dart' as globals;
 import '../build_system.dart';
@@ -56,35 +56,39 @@
     final String targetFile = environment.defines[kTargetFile];
     final bool shouldInitializePlatform = environment.defines[kInitializePlatform] == 'true';
     final bool hasPlugins = environment.defines[kHasWebPlugins] == 'true';
-    final String importPath = globals.fs.path.absolute(targetFile);
+    final Uri importUri = environment.fileSystem.file(targetFile).absolute.uri;
+    final PackageConfig packageConfig = await loadPackageConfigUri(
+      environment.projectDir.childFile('.packages').absolute.uri,
+      loader: (Uri uri) {
+        final File file = environment.fileSystem.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
 
-    // Use the package uri mapper to find the correct package-scheme import path
+    // Use the PackageConfig to find the correct package-scheme import path
     // for the user application. If the application has a mix of package-scheme
     // and relative imports for a library, then importing the entrypoint as a
     // file-scheme will cause said library to be recognized as two distinct
     // libraries. This can cause surprising behavior as types from that library
     // will be considered distinct from each other.
-    final PackageUriMapper packageUriMapper = PackageUriMapper(
-      importPath,
-      PackageMap.globalPackagesPath,
-      null,
-      null,
-    );
-
     // By construction, this will only be null if the .packages file does not
     // have an entry for the user's application or if the main file is
     // outside of the lib/ directory.
-    final String mainImport = packageUriMapper.map(importPath)?.toString()
-      ?? globals.fs.file(importPath).absolute.uri.toString();
+    final String mainImport = packageConfig.toPackageUri(importUri)?.toString()
+      ?? importUri.toString();
 
     String contents;
     if (hasPlugins) {
-      final String generatedPath = environment.projectDir
+      final Uri generatedUri = environment.projectDir
         .childDirectory('lib')
         .childFile('generated_plugin_registrant.dart')
-        .absolute.path;
-      final String generatedImport = packageUriMapper.map(generatedPath)?.toString()
-        ?? globals.fs.file(generatedPath).absolute.uri.toString();
+        .absolute
+        .uri;
+      final String generatedImport = packageConfig.toPackageUri(generatedUri)?.toString()
+        ?? generatedUri.toString();
       contents = '''
 import 'dart:ui' as ui;
 
diff --git a/packages/flutter_tools/lib/src/codegen.dart b/packages/flutter_tools/lib/src/codegen.dart
index 8e8c9ac..6126768 100644
--- a/packages/flutter_tools/lib/src/codegen.dart
+++ b/packages/flutter_tools/lib/src/codegen.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 
 import 'base/context.dart';
 import 'build_info.dart';
@@ -72,7 +73,6 @@
     String outputFilePath,
     bool linkPlatformKernelIn = false,
     bool aot = false,
-    @required BuildMode buildMode,
     bool trackWidgetCreation,
     List<String> extraFrontEndOptions,
     String sdkRoot,
@@ -84,6 +84,8 @@
     String initializeFromDill,
     String platformDill,
     List<String> dartDefines,
+    @required BuildMode buildMode,
+    @required PackageConfig packageConfig,
   }) async {
     final FlutterProject flutterProject = FlutterProject.current();
     final CodegenDaemon codegenDaemon = await codeGenerator.daemon(flutterProject);
@@ -113,6 +115,7 @@
       targetModel: targetModel,
       initializeFromDill: initializeFromDill,
       dartDefines: dartDefines,
+      packageConfig: packageConfig,
     );
   }
 }
@@ -170,7 +173,12 @@
   }
 
   @override
-  Future<CompilerOutput> recompile(String mainPath, List<Uri> invalidatedFiles, {String outputPath, String packagesFilePath}) async {
+  Future<CompilerOutput> recompile(
+    Uri mainUri,
+    List<Uri> invalidatedFiles, {
+      String outputPath,
+      PackageConfig packageConfig,
+    }) async {
     if (_codegenDaemon.lastStatus != CodegenStatus.Succeeded && _codegenDaemon.lastStatus != CodegenStatus.Failed) {
       await _codegenDaemon.buildResults.firstWhere((CodegenStatus status) {
         return status == CodegenStatus.Succeeded || status == CodegenStatus.Failed;
@@ -180,10 +188,10 @@
       globals.printError('Code generation failed, build may have compile errors.');
     }
     return _residentCompiler.recompile(
-      mainPath,
+      mainUri,
       invalidatedFiles,
       outputPath: outputPath,
-      packagesFilePath: packagesFilePath,
+      packageConfig: packageConfig,
     );
   }
 
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 0dafd0b..9461343 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 import 'package:usage/uuid/uuid.dart';
 
 import 'artifacts.dart';
@@ -15,7 +16,6 @@
 import 'build_info.dart';
 import 'codegen.dart';
 import 'convert.dart';
-import 'dart/package_map.dart';
 import 'globals.dart' as globals;
 import 'project.dart';
 
@@ -193,54 +193,6 @@
   }
 }
 
-/// Converts filesystem paths to package URIs.
-class PackageUriMapper {
-  PackageUriMapper(String scriptPath, String packagesPath, String fileSystemScheme, List<String> fileSystemRoots) {
-    final Map<String, Uri> packageMap = PackageMap(globals.fs.path.absolute(packagesPath), fileSystem: globals.fs).map;
-    final bool isWindowsPath = globals.platform.isWindows && !scriptPath.startsWith('org-dartlang-app');
-    final String scriptUri = Uri.file(scriptPath, windows: isWindowsPath).toString();
-    for (final String packageName in packageMap.keys) {
-      final String prefix = packageMap[packageName].toString();
-      // Only perform a multi-root mapping if there are multiple roots.
-      if (fileSystemScheme != null
-        && fileSystemRoots != null
-        && fileSystemRoots.length > 1
-        && prefix.contains(fileSystemScheme)) {
-        _packageName = packageName;
-        _uriPrefixes = fileSystemRoots
-          .map((String name) => Uri.file(name, windows:globals.platform.isWindows).toString())
-          .toList();
-        return;
-      }
-      if (scriptUri.startsWith(prefix)) {
-        _packageName = packageName;
-        _uriPrefixes = <String>[prefix];
-        return;
-      }
-    }
-  }
-
-  String _packageName;
-  List<String> _uriPrefixes;
-
-  Uri map(String scriptPath) {
-    if (_packageName == null) {
-      return null;
-    }
-    final String scriptUri = Uri.file(scriptPath, windows: globals.platform.isWindows).toString();
-    for (final String uriPrefix in _uriPrefixes) {
-      if (scriptUri.startsWith(uriPrefix)) {
-        return Uri.parse('package:$_packageName/${scriptUri.substring(uriPrefix.length)}');
-      }
-    }
-    return null;
-  }
-
-  static Uri findUri(String scriptPath, String packagesPath, String fileSystemScheme, List<String> fileSystemRoots) {
-    return PackageUriMapper(scriptPath, packagesPath, fileSystemScheme, fileSystemRoots).map(scriptPath);
-  }
-}
-
 /// List the preconfigured build options for a given build mode.
 List<String> buildModeOptions(BuildMode mode) {
   switch (mode) {
@@ -276,17 +228,18 @@
     String outputFilePath,
     String depFilePath,
     TargetModel targetModel = TargetModel.flutter,
-    @required BuildMode buildMode,
     bool linkPlatformKernelIn = false,
     bool aot = false,
-    @required bool trackWidgetCreation,
     List<String> extraFrontEndOptions,
-    String packagesPath,
     List<String> fileSystemRoots,
     String fileSystemScheme,
     String initializeFromDill,
     String platformDill,
+    @required String packagesPath,
+    @required BuildMode buildMode,
+    @required bool trackWidgetCreation,
     @required List<String> dartDefines,
+    @required PackageConfig packageConfig,
   }) async {
     final String frontendServer = globals.artifacts.getArtifactPath(
       Artifact.frontendServerSnapshotForEngineDartSdk
@@ -301,7 +254,7 @@
     }
     Uri mainUri;
     if (packagesPath != null) {
-      mainUri = PackageUriMapper.findUri(mainPath, packagesPath, fileSystemScheme, fileSystemRoots);
+      mainUri = packageConfig.toPackageUri(globals.fs.file(mainPath).uri);
     }
     // TODO(jonahwilliams): The output file must already exist, but this seems
     // unnecessary.
@@ -392,16 +345,16 @@
 class _RecompileRequest extends _CompilationRequest {
   _RecompileRequest(
     Completer<CompilerOutput> completer,
-    this.mainPath,
+    this.mainUri,
     this.invalidatedFiles,
     this.outputPath,
-    this.packagesFilePath,
+    this.packageConfig,
   ) : super(completer);
 
-  String mainPath;
+  Uri mainUri;
   List<Uri> invalidatedFiles;
   String outputPath;
-  String packagesFilePath;
+  PackageConfig packageConfig;
 
   @override
   Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
@@ -499,10 +452,10 @@
   /// Binary file name is returned if compilation was successful, otherwise
   /// null is returned.
   Future<CompilerOutput> recompile(
-    String mainPath,
+    Uri mainUri,
     List<Uri> invalidatedFiles, {
     @required String outputPath,
-    String packagesFilePath,
+    @required PackageConfig packageConfig,
   });
 
   Future<CompilerOutput> compileExpression(
@@ -620,56 +573,46 @@
 
   @override
   Future<CompilerOutput> recompile(
-    String mainPath,
+    Uri mainUri,
     List<Uri> invalidatedFiles, {
     @required String outputPath,
-    String packagesFilePath,
+    @required PackageConfig packageConfig,
   }) async {
-    assert (outputPath != null);
+    assert(outputPath != null);
     if (!_controller.hasListener) {
       _controller.stream.listen(_handleCompilationRequest);
     }
 
     final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
     _controller.add(
-        _RecompileRequest(completer, mainPath, invalidatedFiles, outputPath, packagesFilePath)
+      _RecompileRequest(completer, mainUri, invalidatedFiles, outputPath, packageConfig)
     );
     return completer.future;
   }
 
   Future<CompilerOutput> _recompile(_RecompileRequest request) async {
     _stdoutHandler.reset();
-
-    // First time recompile is called we actually have to compile the app from
-    // scratch ignoring list of invalidated files.
-    PackageUriMapper packageUriMapper;
-    if (request.packagesFilePath != null || packagesPath != null) {
-      packageUriMapper = PackageUriMapper(
-        request.mainPath,
-        request.packagesFilePath ?? packagesPath,
-        fileSystemScheme,
-        fileSystemRoots,
-      );
-    }
-
     _compileRequestNeedsConfirmation = true;
 
     if (_server == null) {
       return _compile(
-        _mapFilename(request.mainPath, packageUriMapper),
+        request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? request.mainUri.toString(),
         request.outputPath,
-        _mapFilename(request.packagesFilePath ?? packagesPath, /* packageUriMapper= */ null),
       );
     }
-
     final String inputKey = Uuid().generateV4();
-    final String mainUri = request.mainPath != null
-        ? _mapFilename(request.mainPath, packageUriMapper) + ' '
-        : '';
-    _server.stdin.writeln('recompile $mainUri$inputKey');
-    globals.printTrace('<- recompile $mainUri$inputKey');
+    final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString()
+      ?? request.mainUri.toString();
+    _server.stdin.writeln('recompile $mainUri $inputKey');
+    globals.printTrace('<- recompile $mainUri $inputKey');
     for (final Uri fileUri in request.invalidatedFiles) {
-      final String message = _mapFileUri(fileUri.toString(), packageUriMapper);
+      String message;
+      if (fileUri.scheme == 'package') {
+        message = fileUri.toString();
+      } else {
+        message = request.packageConfig.toPackageUri(fileUri)?.toString()
+          ?? fileUri.toString();
+      }
       _server.stdin.writeln(message);
       globals.printTrace(message);
     }
@@ -699,7 +642,6 @@
   Future<CompilerOutput> _compile(
     String scriptUri,
     String outputPath,
-    String packagesFilePath,
   ) async {
     final String frontendServer = globals.artifacts.getArtifactPath(
       Artifact.frontendServerSnapshotForEngineDartSdk
@@ -726,10 +668,7 @@
         '--libraries-spec',
         librariesSpec,
       ],
-      if (packagesFilePath != null) ...<String>[
-        '--packages',
-        packagesFilePath,
-      ] else if (packagesPath != null) ...<String>[
+      if (packagesPath != null) ...<String>[
         '--packages',
         packagesPath,
       ],
@@ -916,43 +855,6 @@
     globals.printTrace('<- reset');
   }
 
-  String _mapFilename(String filename, PackageUriMapper packageUriMapper) {
-    return _doMapFilename(filename, packageUriMapper) ?? filename;
-  }
-
-  String _mapFileUri(String fileUri, PackageUriMapper packageUriMapper) {
-    String filename;
-    try {
-      filename = Uri.parse(fileUri).toFilePath();
-    } on UnsupportedError catch (_) {
-      return fileUri;
-    }
-    return _doMapFilename(filename, packageUriMapper) ?? fileUri;
-  }
-
-  String _doMapFilename(String filename, PackageUriMapper packageUriMapper) {
-    if (packageUriMapper != null) {
-      final Uri packageUri = packageUriMapper.map(filename);
-      if (packageUri != null) {
-        return packageUri.toString();
-      }
-    }
-
-    if (fileSystemRoots != null) {
-      for (final String root in fileSystemRoots) {
-        if (filename.startsWith(root)) {
-          return Uri(
-              scheme: fileSystemScheme, path: filename.substring(root.length))
-              .toString();
-        }
-      }
-    }
-    if (globals.platform.isWindows && fileSystemRoots != null && fileSystemRoots.length > 1) {
-      return Uri.file(filename, windows: globals.platform.isWindows).toString();
-    }
-    return null;
-  }
-
   @override
   Future<dynamic> shutdown() async {
     // Server was never successfully created.
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index db15800..6dcaae3 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 import 'package:vm_service/vm_service.dart' as vmservice;
 
 import 'asset.dart';
@@ -17,7 +18,6 @@
 import 'bundle.dart';
 import 'compile.dart';
 import 'convert.dart' show base64, utf8;
-import 'dart/package_map.dart';
 import 'globals.dart' as globals;
 import 'vmservice.dart';
 
@@ -395,32 +395,28 @@
     VMService serviceProtocol,
     this.fsName,
     this.rootDirectory, {
-    String packagesFilePath,
     @required OperatingSystemUtils osUtils,
   }) : _operations = ServiceProtocolDevFSOperations(serviceProtocol),
        _httpWriter = _DevFSHttpWriter(
         fsName,
         serviceProtocol,
         osUtils: osUtils,
-      ),
-       _packagesFilePath = packagesFilePath ?? globals.fs.path.join(rootDirectory.path, kPackagesFileName);
+      );
 
   DevFS.operations(
     this._operations,
     this.fsName,
-    this.rootDirectory, {
-    String packagesFilePath,
-  }) : _httpWriter = null,
-       _packagesFilePath = packagesFilePath ?? globals.fs.path.join(rootDirectory.path, kPackagesFileName);
+    this.rootDirectory,
+  ) : _httpWriter = null;
 
   final DevFSOperations _operations;
   final _DevFSHttpWriter _httpWriter;
   final String fsName;
   final Directory rootDirectory;
-  final String _packagesFilePath;
   final Set<String> assetPathsToEvict = <String>{};
   List<Uri> sources = <Uri>[];
   DateTime lastCompiled;
+  PackageConfig lastPackageConfig;
 
   Uri _baseUri;
   Uri get baseUri => _baseUri;
@@ -462,23 +458,25 @@
   ///
   /// Returns the number of bytes synced.
   Future<UpdateFSReport> update({
-    @required String mainPath,
+    @required Uri mainUri,
+    @required ResidentCompiler generator,
+    @required bool trackWidgetCreation,
+    @required String pathToReload,
+    @required List<Uri> invalidatedFiles,
+    @required PackageConfig packageConfig,
     String target,
     AssetBundle bundle,
     DateTime firstBuildTime,
     bool bundleFirstUpload = false,
-    @required ResidentCompiler generator,
     String dillOutputPath,
-    @required bool trackWidgetCreation,
     bool fullRestart = false,
     String projectRootPath,
-    @required String pathToReload,
-    @required List<Uri> invalidatedFiles,
     bool skipAssets = false,
   }) async {
     assert(trackWidgetCreation != null);
     assert(generator != null);
     final DateTime candidateCompileTime = DateTime.now();
+    lastPackageConfig = packageConfig;
 
     // Update modified files
     final String assetBuildDirPrefix = _asUriPath(getAssetBuildDirectory());
@@ -514,10 +512,10 @@
     // dill files that depend on the invalidated files.
     globals.printTrace('Compiling dart to kernel with ${invalidatedFiles.length} updated files');
     final CompilerOutput compilerOutput = await generator.recompile(
-      mainPath,
+      mainUri,
       invalidatedFiles,
-      outputPath:  dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
-      packagesFilePath : _packagesFilePath,
+      outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
+      packageConfig: packageConfig,
     );
     if (compilerOutput == null || compilerOutput.errorCount > 0) {
       return UpdateFSReport(success: false);
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 50eac66..816e488 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -7,6 +7,7 @@
 import 'package:vm_service/vm_service.dart' as vm_service;
 import 'package:devtools_server/devtools_server.dart' as devtools_server;
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 
 import 'application_package.dart';
 import 'artifacts.dart';
@@ -58,6 +59,7 @@
          targetModel: targetModel,
          experimentalFlags: experimentalFlags,
          dartDefines: buildInfo.dartDefines,
+         packagesPath: PackageMap.globalPackagesPath,
        );
 
   /// Create a [FlutterDevice] with optional code generation enabled.
@@ -104,7 +106,8 @@
           .absolute.uri.toString(),
         dartDefines: buildInfo.dartDefines,
         librariesSpec: globals.fs.file(globals.artifacts
-          .getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString()
+          .getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString(),
+        packagesPath: PackageMap.globalPackagesPath,
       );
     } else {
       generator = ResidentCompiler(
@@ -121,6 +124,7 @@
         experimentalFlags: experimentalFlags,
         dartDefines: buildInfo.dartDefines,
         initializeFromDill: globals.fs.path.join(getBuildDirectory(), 'cache.dill'),
+        packagesPath: PackageMap.globalPackagesPath,
       );
     }
 
@@ -285,7 +289,6 @@
       vmService,
       fsName,
       rootDirectory,
-      packagesFilePath: packagesFilePath,
       osUtils: globals.os,
     );
     return devFS.create();
@@ -548,7 +551,7 @@
   }
 
   Future<UpdateFSReport> updateDevFS({
-    String mainPath,
+    Uri mainUri,
     String target,
     AssetBundle bundle,
     DateTime firstBuildTime,
@@ -559,6 +562,7 @@
     String pathToReload,
     @required String dillOutputPath,
     @required List<Uri> invalidatedFiles,
+    @required PackageConfig packageConfig,
   }) async {
     final Status devFSStatus = globals.logger.startProgress(
       'Syncing files to device ${device.name}...',
@@ -567,7 +571,7 @@
     UpdateFSReport report;
     try {
       report = await devFS.update(
-        mainPath: mainPath,
+        mainUri: mainUri,
         target: target,
         bundle: bundle,
         firstBuildTime: firstBuildTime,
@@ -579,6 +583,7 @@
         projectRootPath: projectRootPath,
         pathToReload: pathToReload,
         invalidatedFiles: invalidatedFiles,
+        packageConfig: packageConfig,
       );
     } on DevFSException {
       devFSStatus.cancel();
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index 82d1fc1..55094f4 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'package:package_config/package_config.dart';
 import 'package:vm_service/vm_service.dart' as vm_service;
 import 'package:platform/platform.dart';
 import 'package:meta/meta.dart';
@@ -17,6 +18,7 @@
 import 'bundle.dart';
 import 'compile.dart';
 import 'convert.dart';
+import 'dart/package_map.dart';
 import 'devfs.dart';
 import 'device.dart';
 import 'globals.dart' as globals;
@@ -151,13 +153,23 @@
   }
 
   @override
-  Future<OperationResult> reloadMethod({String libraryId, String classId}) async {
+  Future<OperationResult> reloadMethod({ String libraryId, String classId }) async {
     final Stopwatch stopwatch = Stopwatch()..start();
     final UpdateFSReport results = UpdateFSReport(success: true);
     final List<Uri> invalidated =  <Uri>[Uri.parse(libraryId)];
+    final PackageConfig packageConfig = await loadPackageConfigUri(
+      globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
+      loader: (Uri uri) {
+        final File file = globals.fs.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
     for (final FlutterDevice device in flutterDevices) {
       results.incorporateResults(await device.updateDevFS(
-        mainPath: mainPath,
+        mainUri: globals.fs.file(mainPath).absolute.uri,
         target: target,
         bundle: assetBundle,
         firstBuildTime: firstBuildTime,
@@ -167,6 +179,7 @@
         projectRootPath: projectRootPath,
         pathToReload: getReloadPath(fullRestart: false),
         invalidatedFiles: invalidated,
+        packageConfig: packageConfig,
         dillOutputPath: dillOutputPath,
       ));
     }
@@ -345,6 +358,16 @@
     firstBuildTime = DateTime.now();
 
     final List<Future<bool>> startupTasks = <Future<bool>>[];
+    final PackageConfig packageConfig = await loadPackageConfigUri(
+      globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
+      loader: (Uri uri) {
+        final File file = globals.fs.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
     for (final FlutterDevice device in flutterDevices) {
       // Here we initialize the frontend_server concurrently with the platform
       // build, reducing overall initialization time. This is safe because the first
@@ -353,11 +376,11 @@
       if (device.generator != null) {
         startupTasks.add(
           device.generator.recompile(
-            mainPath,
+            globals.fs.file(mainPath).uri,
             <Uri>[],
             outputPath: dillOutputPath ??
               getDefaultApplicationKernelPath(trackWidgetCreation: debuggingOptions.buildInfo.trackWidgetCreation),
-            packagesFilePath : packagesFilePath,
+            packageConfig: packageConfig,
           ).then((CompilerOutput output) => output?.errorCount == 0)
         );
       }
@@ -405,18 +428,17 @@
       }
     }
 
-    // Picking up first device's compiler as a source of truth - compilers
-    // for all devices should be in sync.
-    final List<Uri> invalidatedFiles = await projectFileInvalidator.findInvalidated(
+    final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
       lastCompiled: flutterDevices[0].devFS.lastCompiled,
       urisToMonitor: flutterDevices[0].devFS.sources,
       packagesPath: packagesFilePath,
       asyncScanning: hotRunnerConfig.asyncScanning,
+      packageConfig: flutterDevices[0].devFS.lastPackageConfig,
     );
     final UpdateFSReport results = UpdateFSReport(success: true);
     for (final FlutterDevice device in flutterDevices) {
       results.incorporateResults(await device.updateDevFS(
-        mainPath: mainPath,
+        mainUri: globals.fs.file(mainPath).absolute.uri,
         target: target,
         bundle: assetBundle,
         firstBuildTime: firstBuildTime,
@@ -425,7 +447,8 @@
         fullRestart: fullRestart,
         projectRootPath: projectRootPath,
         pathToReload: getReloadPath(fullRestart: fullRestart),
-        invalidatedFiles: invalidatedFiles,
+        invalidatedFiles: invalidationResult.uris,
+        packageConfig: invalidationResult.packageConfig,
         dillOutputPath: dillOutputPath,
       ));
     }
@@ -1156,6 +1179,17 @@
   }
 }
 
+/// The result of an invalidation check from [ProjectFileInvalidator].
+class InvalidationResult {
+  const InvalidationResult({
+    this.uris,
+    this.packageConfig,
+  });
+
+  final List<Uri> uris;
+  final PackageConfig packageConfig;
+}
+
 /// The [ProjectFileInvalidator] track the dependencies for a running
 /// application to determine when they are dirty.
 class ProjectFileInvalidator {
@@ -1182,10 +1216,11 @@
   // ~2000 files.
   static const int _kMaxPendingStats = 8;
 
-  Future<List<Uri>> findInvalidated({
+  Future<InvalidationResult> findInvalidated({
     @required DateTime lastCompiled,
     @required List<Uri> urisToMonitor,
     @required String packagesPath,
+    @required PackageConfig packageConfig,
     bool asyncScanning = false,
   }) async {
     assert(urisToMonitor != null);
@@ -1194,7 +1229,10 @@
     if (lastCompiled == null) {
       // Initial load.
       assert(urisToMonitor.isEmpty);
-      return <Uri>[];
+      return InvalidationResult(
+        packageConfig: await _createPackageConfig(packagesPath),
+        uris: <Uri>[]
+      );
     }
 
     final Stopwatch stopwatch = Stopwatch()..start();
@@ -1202,9 +1240,6 @@
       // Don't watch pub cache directories to speed things up a little.
       for (final Uri uri in urisToMonitor)
         if (_isNotInPubCache(uri)) uri,
-
-      // We need to check the .packages file too since it is not used in compilation.
-      _fileSystem.file(packagesPath).uri,
     ];
     final List<Uri> invalidatedFiles = <Uri>[];
 
@@ -1233,16 +1268,41 @@
         }
       }
     }
+    // We need to check the .packages file too since it is not used in compilation.
+    final Uri packageUri = _fileSystem.file(packagesPath).uri;
+    final DateTime updatedAt = _fileSystem.statSync(
+      packageUri.toFilePath(windows: _platform.isWindows)).modified;
+    if (updatedAt != null && updatedAt.isAfter(lastCompiled)) {
+      invalidatedFiles.add(packageUri);
+      packageConfig = await _createPackageConfig(packagesPath);
+    }
+
     _logger.printTrace(
       'Scanned through ${urisToScan.length} files in '
       '${stopwatch.elapsedMilliseconds}ms'
       '${asyncScanning ? " (async)" : ""}',
     );
-    return invalidatedFiles;
+    return InvalidationResult(
+      packageConfig: packageConfig,
+      uris: invalidatedFiles,
+    );
   }
 
   bool _isNotInPubCache(Uri uri) {
     return !(_platform.isWindows && uri.path.contains(_pubCachePathWindows))
         && !uri.path.contains(_pubCachePathLinuxAndMac);
   }
+
+  Future<PackageConfig> _createPackageConfig(String packagesPath) {
+    return loadPackageConfigUri(
+      _fileSystem.file(packagesPath).absolute.uri,
+      loader: (Uri uri) {
+        final File file = _fileSystem.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
+  }
 }
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index 025a455..a27aa8f 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -448,7 +448,7 @@
       if (precompiledDillPath == null && precompiledDillFiles == null) {
         // Lazily instantiate compiler so it is built only if it is actually used.
         compiler ??= TestCompiler(buildMode, trackWidgetCreation, flutterProject);
-        mainDart = await compiler.compile(mainDart);
+        mainDart = await compiler.compile(globals.fs.file(mainDart).uri);
 
         if (mainDart == null) {
           controller.sink.addError(_getErrorMessage('Compilation failed', testPath, shellPath));
diff --git a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart
index fcd7bd5..fa153ec 100644
--- a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart
@@ -869,7 +869,7 @@
 
     // Lazily create the compiler
     _compiler = _compiler ?? compilerFactory();
-    final String output = await _compiler.compile(listenerFile.path);
+    final String output = await _compiler.compile(listenerFile.uri);
     final List<String> command = <String>[
       shellPath,
       '--disable-observatory',
diff --git a/packages/flutter_tools/lib/src/test/test_compiler.dart b/packages/flutter_tools/lib/src/test/test_compiler.dart
index dac2fb7..c569c37 100644
--- a/packages/flutter_tools/lib/src/test/test_compiler.dart
+++ b/packages/flutter_tools/lib/src/test/test_compiler.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:meta/meta.dart';
+import 'package:package_config/package_config.dart';
 
 import '../artifacts.dart';
 import '../base/file_system.dart';
@@ -19,8 +20,9 @@
 
 /// A request to the [TestCompiler] for recompilation.
 class _CompilationRequest {
-  _CompilationRequest(this.path, this.result);
-  String path;
+  _CompilationRequest(this.mainUri, this.result);
+
+  Uri mainUri;
   Completer<String> result;
 }
 
@@ -70,7 +72,7 @@
   // Whether to report compiler messages.
   bool _suppressOutput = false;
 
-  Future<String> compile(String mainDart) {
+  Future<String> compile(Uri mainDart) {
     final Completer<String> completer = Completer<String>();
     compilerController.add(_CompilationRequest(mainDart, completer));
     return completer.future;
@@ -95,13 +97,13 @@
   Future<ResidentCompiler> createCompiler() async {
     final ResidentCompiler residentCompiler = ResidentCompiler(
       globals.artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
-      packagesPath: PackageMap.globalPackagesPath,
       buildMode: buildMode,
       trackWidgetCreation: trackWidgetCreation,
       compilerMessageConsumer: _reportCompilerMessage,
       initializeFromDill: testFilePath,
       unsafePackageSerialization: false,
       dartDefines: const <String>[],
+      packagesPath: PackageMap.globalPackagesPath,
     );
     if (flutterProject.hasBuilders) {
       return CodeGeneratingResidentCompiler.create(
@@ -112,6 +114,8 @@
     return residentCompiler;
   }
 
+  PackageConfig _packageConfig;
+
   // Handle a compilation request.
   Future<void> _onCompilationRequest(_CompilationRequest request) async {
     final bool isEmpty = compilationQueue.isEmpty;
@@ -122,9 +126,19 @@
     if (!isEmpty) {
       return;
     }
+    _packageConfig ??= await loadPackageConfigUri(
+      globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
+      loader: (Uri uri) async {
+        final File file = globals.fs.file(uri);
+        if (!file.existsSync()) {
+          return null;
+        }
+        return file.readAsBytes();
+      }
+    );
     while (compilationQueue.isNotEmpty) {
       final _CompilationRequest request = compilationQueue.first;
-      globals.printTrace('Compiling ${request.path}');
+      globals.printTrace('Compiling ${request.mainUri}');
       final Stopwatch compilerTime = Stopwatch()..start();
       bool firstCompile = false;
       if (compiler == null) {
@@ -133,9 +147,10 @@
       }
       _suppressOutput = false;
       final CompilerOutput compilerOutput = await compiler.recompile(
-        request.path,
-        <Uri>[Uri.parse(request.path)],
+        request.mainUri,
+        <Uri>[request.mainUri],
         outputPath: outputDill.path,
+        packageConfig: _packageConfig,
       );
       final String outputPath = compilerOutput?.outputFilename;
 
@@ -143,12 +158,13 @@
       // errors, pass [null] upwards to the consumer and shutdown the
       // compiler to avoid reusing compiler that might have gotten into
       // a weird state.
+      final String path = request.mainUri.toFilePath(windows: globals.platform.isWindows);
       if (outputPath == null || compilerOutput.errorCount > 0) {
         request.result.complete(null);
         await _shutdown();
       } else {
         final File outputFile = globals.fs.file(outputPath);
-        final File kernelReadyToRun = await outputFile.copy('${request.path}.dill');
+        final File kernelReadyToRun = await outputFile.copy('$path.dill');
         final File testCache = globals.fs.file(testFilePath);
         if (firstCompile || !testCache.existsSync() || (testCache.lengthSync() < outputFile.lengthSync())) {
           // The idea is to keep the cache file up-to-date and include as
@@ -161,7 +177,7 @@
         compiler.accept();
         compiler.reset();
       }
-      globals.printTrace('Compiling ${request.path} took ${compilerTime.elapsedMilliseconds}ms');
+      globals.printTrace('Compiling $path took ${compilerTime.elapsedMilliseconds}ms');
       // Only remove now when we finished processing the element
       compilationQueue.removeAt(0);
     }
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
index 6a0380d..ee6a1ee 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart
@@ -140,7 +140,7 @@
 
     // Import.
     expect(generated, contains("import 'file:///other/lib/main.dart' as entrypoint;"));
-    expect(generated, contains("import 'file:///foo/lib/generated_plugin_registrant.dart';"));
+    expect(generated, contains("import 'package:foo/generated_plugin_registrant.dart';"));
   }));
 
 
diff --git a/packages/flutter_tools/test/general.shard/compile_batch_test.dart b/packages/flutter_tools/test/general.shard/compile_batch_test.dart
index 88ccfb1..801d8e4 100644
--- a/packages/flutter_tools/test/general.shard/compile_batch_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_batch_test.dart
@@ -11,6 +11,7 @@
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
 import 'package:mockito/mockito.dart';
+import 'package:package_config/package_config.dart';
 import 'package:process/process.dart';
 import 'package:platform/platform.dart';
 
@@ -59,6 +60,8 @@
       buildMode: BuildMode.debug,
       trackWidgetCreation: false,
       dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
@@ -88,6 +91,8 @@
       trackWidgetCreation: false,
       aot: true,
       dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
@@ -121,6 +126,8 @@
       trackWidgetCreation: false,
       aot: true,
       dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
@@ -152,6 +159,8 @@
       buildMode: BuildMode.debug,
       trackWidgetCreation: false,
       dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
@@ -179,6 +188,8 @@
       buildMode: BuildMode.debug,
       trackWidgetCreation: false,
       dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
     expect(testLogger.errorText, equals('\nCompiler message:\nline1\nline2\n'));
@@ -201,6 +212,8 @@
       buildMode: BuildMode.debug,
       trackWidgetCreation: false,
       dartDefines: const <String>['FOO=bar', 'BAZ=qux'],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
     );
 
     expect(latestCommand, containsAllInOrder(<String>['-DFOO=bar', '-DBAZ=qux']));
diff --git a/packages/flutter_tools/test/general.shard/compile_expression_test.dart b/packages/flutter_tools/test/general.shard/compile_expression_test.dart
index 9f28534..4d6e274 100644
--- a/packages/flutter_tools/test/general.shard/compile_expression_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_expression_test.dart
@@ -10,7 +10,9 @@
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
+import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:mockito/mockito.dart';
+import 'package:package_config/package_config.dart';
 import 'package:process/process.dart';
 import 'package:platform/platform.dart';
 
@@ -74,12 +76,13 @@
     )));
 
     await generator.recompile(
-      '/path/to/main.dart',
+      globals.fs.file('/path/to/main.dart').uri,
       null, /* invalidatedFiles */
       outputPath: '/build/',
+      packageConfig: PackageConfig.empty,
     ).then((CompilerOutput output) {
       expect(mockFrontendServerStdIn.getAndClear(),
-          'compile /path/to/main.dart\n');
+          'compile file:///path/to/main.dart\n');
       verifyNoMoreInteractions(mockFrontendServerStdIn);
       expect(testLogger.errorText,
           equals('\nCompiler message:\nline1\nline2\n'));
@@ -122,9 +125,10 @@
     // The test manages timing via completers.
     unawaited(
       generator.recompile(
-        '/path/to/main.dart',
+        Uri.parse('/path/to/main.dart'),
         null, /* invalidatedFiles */
         outputPath: '/build/',
+        packageConfig: PackageConfig.empty,
       ).then((CompilerOutput outputCompile) {
         expect(testLogger.errorText,
             equals('\nCompiler message:\nline1\nline2\n'));
diff --git a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
index a1d9b08..77aafcb 100644
--- a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
@@ -11,6 +11,7 @@
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
 import 'package:mockito/mockito.dart';
+import 'package:package_config/package_config.dart';
 import 'package:process/process.dart';
 import 'package:platform/platform.dart';
 
@@ -58,9 +59,10 @@
         ));
 
     final CompilerOutput output = await generator.recompile(
-      '/path/to/main.dart',
+      Uri.parse('/path/to/main.dart'),
         null /* invalidatedFiles */,
       outputPath: '/build/',
+      packageConfig: PackageConfig.empty,
     );
     expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
     verifyNoMoreInteractions(mockFrontendServerStdIn);
@@ -78,9 +80,10 @@
     );
 
     expect(asyncGuard(() => generator.recompile(
-      '/path/to/main.dart',
+      Uri.parse('/path/to/main.dart'),
       null, /* invalidatedFiles */
       outputPath: '/build/',
+      packageConfig: PackageConfig.empty,
     )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
@@ -96,9 +99,10 @@
     );
 
     expect(asyncGuard(() => generator.recompile(
-      '/path/to/main.dart',
+      Uri.parse('/path/to/main.dart'),
       null, /* invalidatedFiles */
       outputPath: '/build/',
+      packageConfig: PackageConfig.empty,
     )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
@@ -112,9 +116,10 @@
         .thenAnswer((Invocation invocation) => streamController.stream);
     streamController.add(utf8.encode('result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0\n'));
     await generator.recompile(
-      '/path/to/main.dart',
+      Uri.parse('/path/to/main.dart'),
       null, /* invalidatedFiles */
       outputPath: '/build/',
+      packageConfig: PackageConfig.empty,
     );
     expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
 
@@ -153,7 +158,12 @@
     streamController.add(utf8.encode(
       'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0\n'
     ));
-    await generator.recompile('/path/to/main.dart', null /* invalidatedFiles */, outputPath: '/build/');
+    await generator.recompile(
+      Uri.parse('/path/to/main.dart'),
+      null /* invalidatedFiles */,
+      outputPath: '/build/',
+       packageConfig: PackageConfig.empty,
+    );
     expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
 
     await _recompile(streamController, generator, mockFrontendServerStdIn,
@@ -187,16 +197,18 @@
     streamController.add(utf8.encode(mockCompilerOutput));
   });
   final CompilerOutput output = await generator.recompile(
-    null /* mainPath */,
+    Uri.parse('/path/to/main.dart'),
     <Uri>[Uri.parse('/path/to/main.dart')],
     outputPath: '/build/',
+    packageConfig: PackageConfig.empty,
   );
   expect(output.outputFilename, equals('/path/to/main.dart.dill'));
   final String commands = mockFrontendServerStdIn.getAndClear();
-  final RegExp re = RegExp(r'^recompile (.*)\n/path/to/main.dart\n(.*)\n$');
-  expect(commands, matches(re));
-  final Match match = re.firstMatch(commands);
-  expect(match[1] == match[2], isTrue);
+  final RegExp whitespace = RegExp(r'\s+');
+  final List<String> parts = commands.split(whitespace);
+
+  // Test that uuid matches at beginning and end.
+  expect(parts[2], equals(parts[4]));
   mockFrontendServerStdIn.stdInWrites.clear();
 }
 
diff --git a/packages/flutter_tools/test/general.shard/devfs_test.dart b/packages/flutter_tools/test/general.shard/devfs_test.dart
index f85f99e..2970cec 100644
--- a/packages/flutter_tools/test/general.shard/devfs_test.dart
+++ b/packages/flutter_tools/test/general.shard/devfs_test.dart
@@ -16,6 +16,7 @@
 import 'package:flutter_tools/src/devfs.dart';
 import 'package:flutter_tools/src/vmservice.dart';
 import 'package:mockito/mockito.dart';
+import 'package:package_config/package_config.dart';
 import 'package:vm_service/vm_service.dart' as vm_service;
 
 import '../src/common.dart';
@@ -160,11 +161,12 @@
 
         final MockResidentCompiler residentCompiler = MockResidentCompiler();
         final UpdateFSReport report = await devFS.update(
-          mainPath: 'lib/foo.txt',
+          mainUri: Uri.parse('lib/foo.txt'),
           generator: residentCompiler,
           pathToReload: 'lib/foo.txt.dill',
           trackWidgetCreation: false,
           invalidatedFiles: <Uri>[],
+          packageConfig: PackageConfig.empty,
         );
 
         expect(report.syncedBytes, 22);
@@ -221,11 +223,12 @@
       expect(devFS.assetPathsToEvict, isEmpty);
 
       final UpdateFSReport report = await devFS.update(
-        mainPath: 'lib/foo.txt',
+        mainUri: Uri.parse('lib/foo.txt'),
         generator: residentCompiler,
         pathToReload: 'lib/foo.txt.dill',
         trackWidgetCreation: false,
         invalidatedFiles: <Uri>[],
+        packageConfig: PackageConfig.empty,
       );
       vmService.expectMessages(<String>[
         'writeFile test lib/foo.txt.dill',
@@ -284,17 +287,18 @@
         any,
         any,
         outputPath: anyNamed('outputPath'),
-        packagesFilePath: anyNamed('packagesFilePath'),
+        packageConfig: anyNamed('packageConfig'),
       )).thenAnswer((Invocation invocation) {
         return Future<CompilerOutput>.value(const CompilerOutput('example', 2, <Uri>[]));
       });
 
       final UpdateFSReport report = await devFS.update(
-        mainPath: 'lib/foo.txt',
+        mainUri: Uri.parse('lib/foo.txt'),
         generator: residentCompiler,
         pathToReload: 'lib/foo.txt.dill',
         trackWidgetCreation: false,
         invalidatedFiles: <Uri>[],
+        packageConfig: PackageConfig.empty,
       );
 
       expect(report.success, false);
@@ -316,18 +320,19 @@
         any,
         any,
         outputPath: anyNamed('outputPath'),
-        packagesFilePath: anyNamed('packagesFilePath'),
+        packageConfig: anyNamed('packageConfig'),
       )).thenAnswer((Invocation invocation) {
         fs.file('example').createSync();
         return Future<CompilerOutput>.value(CompilerOutput('example', 0, <Uri>[sourceFile.uri]));
       });
 
       final UpdateFSReport report = await devFS.update(
-        mainPath: 'lib/main.dart',
+        mainUri: Uri.parse('lib/main.dart'),
         generator: residentCompiler,
         pathToReload: 'lib/foo.txt.dill',
         trackWidgetCreation: false,
         invalidatedFiles: <Uri>[],
+        packageConfig: PackageConfig.empty,
       );
 
       expect(report.success, true);
diff --git a/packages/flutter_tools/test/general.shard/hot_test.dart b/packages/flutter_tools/test/general.shard/hot_test.dart
index 15587d6..9a7d34f 100644
--- a/packages/flutter_tools/test/general.shard/hot_test.dart
+++ b/packages/flutter_tools/test/general.shard/hot_test.dart
@@ -103,7 +103,7 @@
     MockLocalEngineArtifacts mockArtifacts;
 
     when(mockDevFs.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -115,6 +115,7 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation _) => Future<UpdateFSReport>.value(
         UpdateFSReport(success: true, syncedBytes: 1000, invalidatedSourcesCount: 1)));
     when(mockDevFs.assetPathsToEvict).thenReturn(<String>{});
diff --git a/packages/flutter_tools/test/general.shard/package_uri_mapper_test.dart b/packages/flutter_tools/test/general.shard/package_uri_mapper_test.dart
deleted file mode 100644
index c03f3df..0000000
--- a/packages/flutter_tools/test/general.shard/package_uri_mapper_test.dart
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Flutter Authors. 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:typed_data';
-
-import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/compile.dart';
-import 'package:flutter_tools/src/convert.dart';
-import 'package:flutter_tools/src/globals.dart' as globals;
-import 'package:mockito/mockito.dart';
-
-import '../src/common.dart';
-import '../src/context.dart';
-
-const String packagesContents = r'''
-xml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/xml-3.2.3/lib/
-yaml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.15/lib/
-example:file:///example/lib/
-''';
-
-const String multiRootPackagesContents = r'''
-xml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/xml-3.2.3/lib/
-yaml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.15/lib/
-example:org-dartlang-app:/
-''';
-
-void main() {
-  MockFileSystem mockFileSystem;
-  MockFile mockFile;
-
-  setUp(() {
-    mockFileSystem = MockFileSystem();
-    mockFile = MockFile();
-    when(mockFileSystem.path).thenReturn(globals.fs.path);
-    when(mockFileSystem.file(any)).thenReturn(mockFile);
-    when(mockFile.readAsBytesSync()).thenReturn(utf8.encode(packagesContents) as Uint8List);
-  });
-
-  testUsingContext('Can map main.dart to correct package', () async {
-    final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
-    expect(packageUriMapper.map('/example/lib/main.dart').toString(),
-        'package:example/main.dart');
-  }, overrides: <Type, Generator>{
-    FileSystem: () => mockFileSystem,
-    ProcessManager: () => FakeProcessManager.any(),
-  });
-
-  testUsingContext('single-root maps file from other package to null', () async {
-    final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
-    expect(packageUriMapper.map('/xml/lib/xml.dart'), null);
-  }, overrides: <Type, Generator>{
-    FileSystem: () => mockFileSystem,
-    ProcessManager: () => FakeProcessManager.any(),
-  });
-
-  testUsingContext('single-root maps non-main file from same package', () async {
-    final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
-    expect(packageUriMapper.map('/example/lib/src/foo.dart').toString(),
-        'package:example/src/foo.dart');
-  }, overrides: <Type, Generator>{
-    FileSystem: () => mockFileSystem,
-    ProcessManager: () => FakeProcessManager.any(),
-  });
-
-  testUsingContext('multi-root maps main file from same package on multiroot scheme', () async {
-    final MockFileSystem mockFileSystem = MockFileSystem();
-    final MockFile mockFile = MockFile();
-    when(mockFileSystem.path).thenReturn(globals.fs.path);
-    when(mockFileSystem.file(any)).thenReturn(mockFile);
-    when(mockFile.readAsBytesSync())
-        .thenReturn(utf8.encode(multiRootPackagesContents) as Uint8List);
-    final PackageUriMapper packageUriMapper = PackageUriMapper(
-        '/example/lib/main.dart',
-        '.packages',
-        'org-dartlang-app',
-        <String>['/example/lib/', '/gen/lib/']);
-    expect(packageUriMapper.map('/example/lib/main.dart').toString(),
-        'package:example/main.dart');
-  }, overrides: <Type, Generator>{
-    FileSystem: () => mockFileSystem,
-    ProcessManager: () => FakeProcessManager.any(),
-  });
-}
-
-class MockFileSystem extends Mock implements FileSystem {}
-class MockFile extends Mock implements File {}
diff --git a/packages/flutter_tools/test/general.shard/project_file_invalidator_test.dart b/packages/flutter_tools/test/general.shard/project_file_invalidator_test.dart
index 70d50b80..24bb962 100644
--- a/packages/flutter_tools/test/general.shard/project_file_invalidator_test.dart
+++ b/packages/flutter_tools/test/general.shard/project_file_invalidator_test.dart
@@ -3,84 +3,123 @@
 // found in the LICENSE file.
 
 import 'package:file/memory.dart';
+import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/logger.dart';
-import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/run_hot.dart';
+import 'package:package_config/package_config.dart';
 
 import 'package:platform/platform.dart';
 
 import '../src/common.dart';
-import '../src/mocks.dart';
 
 // assumption: tests have a timeout less than 100 days
 final DateTime inFuture = DateTime.now().add(const Duration(days: 100));
 
 void main() {
-  BufferLogger bufferLogger;
-
-  setUp(() {
-    bufferLogger = BufferLogger(
-      terminal: AnsiTerminal(
-        stdio: MockStdio(),
-        platform: FakePlatform(),
-      ),
-      outputPreferences: OutputPreferences.test(),
-    );
-  });
-
   for (final bool asyncScanning in <bool>[true, false]) {
     testWithoutContext('No last compile, asyncScanning: $asyncScanning', () async {
+      final FileSystem fileSystem = MemoryFileSystem();
       final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
-        fileSystem: MemoryFileSystem(),
+        fileSystem: fileSystem,
         platform: FakePlatform(),
-        logger: bufferLogger,
+        logger: BufferLogger.test(),
       );
+      fileSystem.file('.packages').writeAsStringSync('\n');
 
       expect(
-        await projectFileInvalidator.findInvalidated(
+        (await projectFileInvalidator.findInvalidated(
           lastCompiled: null,
           urisToMonitor: <Uri>[],
-          packagesPath: '',
+          packagesPath: '.packages',
           asyncScanning: asyncScanning,
-        ),
+          packageConfig: PackageConfig.empty,
+        )).uris,
         isEmpty,
       );
     });
 
     testWithoutContext('Empty project, asyncScanning: $asyncScanning', () async {
+      final FileSystem fileSystem = MemoryFileSystem();
       final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
-        fileSystem: MemoryFileSystem(),
+        fileSystem: fileSystem,
         platform: FakePlatform(),
-        logger: bufferLogger,
+        logger: BufferLogger.test(),
       );
+      fileSystem.file('.packages').writeAsStringSync('\n');
 
       expect(
-        await projectFileInvalidator.findInvalidated(
+        (await projectFileInvalidator.findInvalidated(
           lastCompiled: inFuture,
           urisToMonitor: <Uri>[],
-          packagesPath: '',
+          packagesPath: '.packages',
           asyncScanning: asyncScanning,
-        ),
+          packageConfig: PackageConfig.empty,
+        )).uris,
         isEmpty,
       );
     });
 
     testWithoutContext('Non-existent files are ignored, asyncScanning: $asyncScanning', () async {
+      final FileSystem fileSystem = MemoryFileSystem();
       final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
         fileSystem: MemoryFileSystem(),
         platform: FakePlatform(),
-        logger: bufferLogger,
+        logger: BufferLogger.test(),
       );
+      fileSystem.file('.packages').writeAsStringSync('\n');
 
       expect(
-        await projectFileInvalidator.findInvalidated(
+        (await projectFileInvalidator.findInvalidated(
           lastCompiled: inFuture,
           urisToMonitor: <Uri>[Uri.parse('/not-there-anymore'),],
-          packagesPath: '',
+          packagesPath: '.packages',
           asyncScanning: asyncScanning,
-        ),
+          packageConfig: PackageConfig.empty,
+        )).uris,
         isEmpty,
       );
     });
+
+    testWithoutContext('Picks up changes to the .packages file and updates PackageConfig'
+      ', asyncScanning: $asyncScanning', () async {
+      final FileSystem fileSystem = MemoryFileSystem.test();
+      final PackageConfig packageConfig = PackageConfig.empty;
+      final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
+        fileSystem: fileSystem,
+        platform: FakePlatform(),
+        logger: BufferLogger.test(),
+      );
+      fileSystem.file('.packages')
+        .writeAsStringSync('\n');
+
+      final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
+        lastCompiled: null,
+        urisToMonitor: <Uri>[],
+        packagesPath: '.packages',
+        asyncScanning: asyncScanning,
+        packageConfig: packageConfig,
+      );
+
+      expect(invalidationResult.packageConfig, isNot(packageConfig));
+
+      fileSystem.file('.packages')
+        .writeAsStringSync('foo:lib/\n');
+      final DateTime packagesUpdated = fileSystem.statSync('.packages')
+        .modified;
+
+      final InvalidationResult nextInvalidationResult = await projectFileInvalidator
+        .findInvalidated(
+          lastCompiled: packagesUpdated.subtract(const Duration(seconds: 1)),
+          urisToMonitor: <Uri>[],
+          packagesPath: '.packages',
+          asyncScanning: asyncScanning,
+          packageConfig: PackageConfig.empty,
+        );
+
+      expect(nextInvalidationResult.uris, contains(Uri.parse('.packages')));
+      // The PackagConfig should have been recreated too
+      expect(nextInvalidationResult.packageConfig,
+        isNot(invalidationResult.packageConfig));
+    });
   }
 }
diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
index 6065f64..5a33104 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -44,6 +44,7 @@
 
   setUp(() {
     testbed = Testbed(setup: () {
+      globals.fs.file('.packages').writeAsStringSync('\n');
       globals.fs.file(globals.fs.path.join('build', 'app.dill'))
         ..createSync(recursive: true)
         ..writeAsStringSync('ABC');
@@ -69,9 +70,8 @@
     when(mockDevFS.assetPathsToEvict).thenReturn(<String>{});
     // FlutterDevice Mocks.
     when(mockFlutterDevice.updateDevFS(
-      // Intentionally provide empty list to match above mock.
-      invalidatedFiles: <Uri>[],
-      mainPath: anyNamed('mainPath'),
+      invalidatedFiles: anyNamed('invalidatedFiles'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -81,6 +81,7 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       dillOutputPath: anyNamed('dillOutputPath'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
       return UpdateFSReport(
         success: true,
@@ -225,7 +226,7 @@
     ));
     await onAppStart.future;
     when(mockFlutterDevice.updateDevFS(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -236,6 +237,7 @@
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
       dillOutputPath: anyNamed('dillOutputPath'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
 
     final OperationResult result = await residentRunner.restart(fullRestart: false);
@@ -330,7 +332,7 @@
     ));
     await onAppStart.future;
     when(mockFlutterDevice.updateDevFS(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -341,6 +343,7 @@
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
       dillOutputPath: anyNamed('dillOutputPath'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
 
     final OperationResult result = await residentRunner.restart(fullRestart: true);
diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
index 8bf049e..b018a46 100644
--- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
@@ -94,7 +94,7 @@
     globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
     globals.fs.file(globals.fs.path.join('web', 'index.html')).createSync(recursive: true);
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -106,6 +106,7 @@
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
       trackWidgetCreation: true,
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation _) async {
       return UpdateFSReport(success: true,  syncedBytes: 0)..invalidatedModules = <String>[];
     });
@@ -313,7 +314,7 @@
     _setupMocks();
     launchChromeInstance(mockChrome);
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -325,9 +326,10 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
       // Generated entrypoint file in temp dir.
-      expect(invocation.namedArguments[#mainPath], contains('entrypoint.dart'));
+      expect(invocation.namedArguments[#mainUri].toString(), contains('entrypoint.dart'));
       return UpdateFSReport(success: true)
         ..invalidatedModules = <String>['example'];
     });
@@ -362,9 +364,9 @@
   test('Can hot restart after attaching', () => testbed.run(() async {
     _setupMocks();
     launchChromeInstance(mockChrome);
-    String entrypointFileName;
+    Uri entrypointFileUri;
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -376,8 +378,9 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
-      entrypointFileName = invocation.namedArguments[#mainPath] as String;
+      entrypointFileUri = invocation.namedArguments[#mainUri] as Uri;
       return UpdateFSReport(success: true)
         ..invalidatedModules = <String>['example'];
     });
@@ -389,8 +392,8 @@
     final OperationResult result = await residentWebRunner.restart(fullRestart: true);
 
     // Ensure that generated entrypoint is generated correctly.
-    expect(entrypointFileName, isNotNull);
-    final String entrypointContents = globals.fs.file(entrypointFileName).readAsStringSync();
+    expect(entrypointFileUri, isNotNull);
+    final String entrypointContents = globals.fs.file(entrypointFileUri).readAsStringSync();
     expect(entrypointContents, contains('// Flutter web bootstrap script'));
     expect(entrypointContents, contains("import 'dart:ui' as ui;"));
     expect(entrypointContents, contains('await ui.webOnlyInitializePlatform();'));
@@ -417,7 +420,7 @@
     _setupMocks();
     when(mockFlutterDevice.device).thenReturn(mockWebServerDevice);
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -429,6 +432,7 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
       return UpdateFSReport(success: true)
         ..invalidatedModules = <String>['example'];
@@ -469,7 +473,7 @@
   test('Exits when initial compile fails', () => testbed.run(() async {
     _setupMocks();
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -480,6 +484,7 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
       trackWidgetCreation: true,
     )).thenAnswer((Invocation _) async {
       return UpdateFSReport(success: false,  syncedBytes: 0)..invalidatedModules = <String>[];
@@ -527,7 +532,7 @@
     ));
     await connectionInfoCompleter.future;
     when(mockWebDevFS.update(
-      mainPath: anyNamed('mainPath'),
+      mainUri: anyNamed('mainUri'),
       target: anyNamed('target'),
       bundle: anyNamed('bundle'),
       firstBuildTime: anyNamed('firstBuildTime'),
@@ -538,6 +543,7 @@
       projectRootPath: anyNamed('projectRootPath'),
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
+      packageConfig: anyNamed('packageConfig'),
       trackWidgetCreation: true,
     )).thenAnswer((Invocation _) async {
       return UpdateFSReport(success: false,  syncedBytes: 0)..invalidatedModules = <String>[];
diff --git a/packages/flutter_tools/test/general.shard/test_compiler_test.dart b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
index c6bc637..4a27324 100644
--- a/packages/flutter_tools/test/general.shard/test_compiler_test.dart
+++ b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
@@ -2,16 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:file_testing/file_testing.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/project.dart';
 import 'package:flutter_tools/src/test/test_compiler.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:mockito/mockito.dart';
+import 'package:platform/platform.dart';
 
 import '../src/common.dart';
 import '../src/testbed.dart';
 
+final Platform linuxPlatform = FakePlatform(
+  operatingSystem: 'linux',
+  environment: <String, String>{},
+);
+
 void main() {
   group(TestCompiler, () {
     Testbed testbed;
@@ -20,6 +27,9 @@
 
     setUp(() {
       testbed = Testbed(
+        overrides: <Type, Generator>{
+          Platform: () => linuxPlatform,
+        },
         setup: () async {
           globals.fs.file('pubspec.yaml').createSync();
           globals.fs.file('.packages').createSync();
@@ -37,37 +47,42 @@
 
     test('Reports a dill file when compile is successful', () => testbed.run(() async {
       when(residentCompiler.recompile(
-        'test/foo.dart',
+        any,
         <Uri>[Uri.parse('test/foo.dart')],
         outputPath: testCompiler.outputDill.path,
+        packageConfig: anyNamed('packageConfig'),
       )).thenAnswer((Invocation invocation) async {
         globals.fs.file('abc.dill').createSync();
         return const CompilerOutput('abc.dill', 0, <Uri>[]);
       });
 
-      expect(await testCompiler.compile('test/foo.dart'), 'test/foo.dart.dill');
-      expect(globals.fs.file('test/foo.dart.dill').existsSync(), true);
+      expect(await testCompiler.compile(Uri.parse('test/foo.dart')), 'test/foo.dart.dill');
+      expect(globals.fs.file('test/foo.dart.dill'), exists);
     }));
 
     test('Reports null when a compile fails', () => testbed.run(() async {
       when(residentCompiler.recompile(
-        'test/foo.dart',
+        any,
         <Uri>[Uri.parse('test/foo.dart')],
         outputPath: testCompiler.outputDill.path,
+        packageConfig: anyNamed('packageConfig'),
       )).thenAnswer((Invocation invocation) async {
         globals.fs.file('abc.dill').createSync();
         return const CompilerOutput('abc.dill', 1, <Uri>[]);
       });
 
-      expect(await testCompiler.compile('test/foo.dart'), null);
-      expect(globals.fs.file('test/foo.dart.dill').existsSync(), false);
+      expect(await testCompiler.compile(Uri.parse('test/foo.dart')), null);
+      expect(globals.fs.file('test/foo.dart.dill'), isNot(exists));
       verify(residentCompiler.shutdown()).called(1);
     }));
 
     test('Disposing test compiler shuts down backing compiler', () => testbed.run(() async {
       testCompiler.compiler = residentCompiler;
+
       expect(testCompiler.compilerController.isClosed, false);
+
       await testCompiler.dispose();
+
       expect(testCompiler.compilerController.isClosed, true);
       verify(residentCompiler.shutdown()).called(1);
     }));
diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
index 911ebf4..db565fe 100644
--- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
@@ -360,7 +360,7 @@
       any,
       any,
       outputPath: anyNamed('outputPath'),
-      packagesFilePath: anyNamed('packagesFilePath'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
       return const CompilerOutput('a', 0, <Uri>[]);
     });
@@ -402,11 +402,12 @@
     webDevFS.webAssetServer.dartSdkSourcemap.createSync(recursive: true);
 
     await webDevFS.update(
-      mainPath: globals.fs.path.join('lib', 'main.dart'),
+      mainUri: globals.fs.file(globals.fs.path.join('lib', 'main.dart')).uri,
       generator: residentCompiler,
       trackWidgetCreation: true,
       bundleFirstUpload: true,
       invalidatedFiles: <Uri>[],
+      packageConfig: PackageConfig.empty,
     );
 
     expect(webDevFS.webAssetServer.getFile('require.js'), isNotNull);
@@ -452,7 +453,7 @@
       any,
       any,
       outputPath: anyNamed('outputPath'),
-      packagesFilePath: anyNamed('packagesFilePath'),
+      packageConfig: anyNamed('packageConfig'),
     )).thenAnswer((Invocation invocation) async {
       return const CompilerOutput('a', 0, <Uri>[]);
     });
diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
index 2d7b8a4..d5df280 100644
--- a/packages/flutter_tools/test/src/mocks.dart
+++ b/packages/flutter_tools/test/src/mocks.dart
@@ -6,6 +6,7 @@
 import 'dart:convert';
 import 'dart:io' as io show IOSink, ProcessSignal, Stdout, StdoutException;
 
+import 'package:package_config/package_config.dart';
 import 'package:platform/platform.dart';
 
 import 'package:flutter_tools/src/android/android_device.dart';
@@ -662,7 +663,7 @@
   }
 
   @override
-  Future<CompilerOutput> recompile(String mainPath, List<Uri> invalidatedFiles, { String outputPath, String packagesFilePath }) async {
+  Future<CompilerOutput> recompile(Uri mainPath, List<Uri> invalidatedFiles, { String outputPath, PackageConfig packageConfig }) async {
     globals.fs.file(outputPath).createSync(recursive: true);
     globals.fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
     return CompilerOutput(outputPath, 0, <Uri>[]);