Revert "[VM/Runtime] Cleanup package config initialization code"

This reverts commit 29e93bcdbdf0c3081999aa247bd3251bf58edbcd.

Reason for revert: Windows bots are failing with package resolution
errors. Looks like we are missing a windows path sanitization step.

Change-Id: Ib56f7e926b4f385fa3fde74c9c71947f64b8be1c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151469
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index abd87c3..021c858 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -100,8 +100,7 @@
     int nullSafety,
     List<String> experimentalFlags,
     bool bytecode,
-    String packageConfig,
-    String workingDirectory,
+    Uri packagesUri,
     List<String> errors) {
   final expFlags = <String>[];
   if (experimentalFlags != null) {
@@ -109,17 +108,7 @@
       expFlags.addAll(flag.split(","));
     }
   }
-  Uri packagesUri = null;
-  if (packageConfig != null) {
-    packagesUri = Uri.parse(packageConfig);
-    if (packagesUri.scheme == '') {
-      // Script does not have a scheme, assume that it is a path,
-      // resolve it against the working directory.
-      packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
-    }
-  } else if (Platform.packageConfig != null) {
-    packagesUri = Uri.parse(Platform.packageConfig);
-  }
+
   return new CompilerOptions()
     ..fileSystem = fileSystem
     ..target = new VmTarget(new TargetFlags(
@@ -169,7 +158,7 @@
   final List<String> experimentalFlags;
   final bool bytecode;
   final String packageConfig;
-  final String workingDirectory;
+
   // Code coverage and hot reload are only supported by incremental compiler,
   // which is used if vm-service is enabled.
   final bool supportCodeCoverage;
@@ -187,8 +176,21 @@
       this.bytecode: false,
       this.supportCodeCoverage: false,
       this.supportHotReload: false,
-      this.packageConfig: null,
-      this.workingDirectory: null}) {
+      this.packageConfig: null}) {
+    Uri packagesUri = null;
+    if (packageConfig != null) {
+      packagesUri = Uri.parse(packageConfig);
+    } else if (Platform.packageConfig != null) {
+      packagesUri = Uri.parse(Platform.packageConfig);
+    }
+
+    if (verbose) {
+      print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
+      print("DFE: packagesUri: ${packagesUri}");
+      print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
+      print("DFE: platformKernelPath: ${platformKernelPath}");
+    }
+
     options = setupCompilerOptions(
         fileSystem,
         platformKernelPath,
@@ -197,16 +199,8 @@
         nullSafety,
         experimentalFlags,
         bytecode,
-        packageConfig,
-        workingDirectory,
+        packagesUri,
         errors);
-
-    if (verbose) {
-      print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
-      print("DFE: packagesUri: ${options.packagesFileUri}");
-      print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
-      print("DFE: platformKernelPath: ${platformKernelPath}");
-    }
   }
 
   Future<CompilerResult> compile(Uri script) {
@@ -343,8 +337,7 @@
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
       bool bytecode: false,
-      String packageConfig: null,
-      String workingDirectory: null})
+      String packageConfig: null})
       : super(isolateId, fileSystem, platformKernelPath,
             suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
@@ -353,8 +346,7 @@
             bytecode: bytecode,
             supportHotReload: true,
             supportCodeCoverage: true,
-            packageConfig: packageConfig,
-            workingDirectory: workingDirectory);
+            packageConfig: packageConfig);
 
   factory IncrementalCompilerWrapper.forExpressionCompilationOnly(
       Component component,
@@ -365,8 +357,7 @@
       bool enableAsserts: false,
       List<String> experimentalFlags: null,
       bool bytecode: false,
-      String packageConfig: null,
-      String workingDirectory: null}) {
+      String packageConfig: null}) {
     IncrementalCompilerWrapper result = IncrementalCompilerWrapper(
         isolateId, fileSystem, platformKernelPath,
         suppressWarnings: suppressWarnings,
@@ -402,8 +393,7 @@
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
         bytecode: bytecode,
-        packageConfig: packageConfig,
-        workingDirectory: workingDirectory);
+        packageConfig: packageConfig);
 
     generator.resetDeltaState();
     Component fullComponent = await generator.compile();
@@ -434,16 +424,14 @@
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
       bool bytecode: false,
-      String packageConfig: null,
-      String workingDirectory: null})
+      String packageConfig: null})
       : super(isolateId, fileSystem, platformKernelPath,
             suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
             nullSafety: nullSafety,
             experimentalFlags: experimentalFlags,
             bytecode: bytecode,
-            packageConfig: packageConfig,
-            workingDirectory: workingDirectory);
+            packageConfig: packageConfig);
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
@@ -479,7 +467,6 @@
     List<String> experimentalFlags: null,
     bool bytecode: false,
     String packageConfig: null,
-    String workingDirectory: null,
     String multirootFilepaths,
     String multirootScheme}) async {
   IncrementalCompilerWrapper compiler = lookupIncrementalCompiler(isolateId);
@@ -493,8 +480,7 @@
     if (sourceFiles != null &&
         sourceFiles.length > 0 &&
         sourceFiles[1] == null) {
-      // Just use first compiler that should represent main isolate as a source
-      // for cloning.
+      // Just use first compiler that should represent main isolate as a source for cloning.
       var source = isolateCompilers.entries.first;
       compiler = await source.value.clone(isolateId);
     } else {
@@ -512,8 +498,7 @@
           nullSafety: nullSafety,
           experimentalFlags: experimentalFlags,
           bytecode: bytecode,
-          packageConfig: packageConfig,
-          workingDirectory: workingDirectory);
+          packageConfig: packageConfig);
     }
     isolateCompilers[isolateId] = compiler;
   }
@@ -837,18 +822,20 @@
   } else if (tag == kDetectNullabilityTag) {
     FileSystem fileSystem = _buildFileSystem(
         sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
+    Uri packagesUri = null;
+    if (packageConfig != null) {
+      packagesUri = Uri.parse(packageConfig);
+    } else if (Platform.packageConfig != null) {
+      packagesUri = Uri.parse(Platform.packageConfig);
+    }
+    if (packagesUri != null && packagesUri.scheme == '') {
+      // Script does not have a scheme, assume that it is a path,
+      // resolve it against the working directory.
+      packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
+    }
     final List<String> errors = <String>[];
-    var options = setupCompilerOptions(
-        fileSystem,
-        platformKernelPath,
-        false,
-        false,
-        nullSafety,
-        experimentalFlags,
-        false,
-        packageConfig,
-        workingDirectory,
-        errors);
+    var options = setupCompilerOptions(fileSystem, platformKernelPath, false,
+        false, nullSafety, experimentalFlags, false, packagesUri, errors);
 
     // script should only be null for kUpdateSourcesTag.
     assert(script != null);
@@ -874,7 +861,6 @@
         experimentalFlags: experimentalFlags,
         bytecode: bytecode,
         packageConfig: packageConfig,
-        workingDirectory: workingDirectory,
         multirootFilepaths: multirootFilepaths,
         multirootScheme: multirootScheme);
   } else {
@@ -888,8 +874,7 @@
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
         bytecode: bytecode,
-        packageConfig: packageConfig,
-        workingDirectory: workingDirectory);
+        packageConfig: packageConfig);
   }
 
   CompilationResult result;
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index f8f374d..f1eeeb2 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -302,6 +302,15 @@
   return Crypto::GetRandomBytes(length, buffer);
 }
 
+static Dart_Handle SingleArgDart_Invoke(Dart_Handle lib,
+                                        const char* method,
+                                        Dart_Handle arg) {
+  const int kNumArgs = 1;
+  Dart_Handle dart_args[kNumArgs];
+  dart_args[0] = arg;
+  return Dart_Invoke(lib, DartUtils::NewString(method), kNumArgs, dart_args);
+}
+
 // TODO(iposva): Allocate from the zone instead of leaking error string
 // here. On the other hand the binary is about to exit anyway.
 #define SET_ERROR_MSG(error_msg, format, ...)                                  \
@@ -361,6 +370,20 @@
   return array;
 }
 
+Dart_Handle DartUtils::SetWorkingDirectory() {
+  Dart_Handle directory = NewString(original_working_directory);
+  return SingleArgDart_Invoke(LookupBuiltinLib(), "_setWorkingDirectory",
+                              directory);
+}
+
+Dart_Handle DartUtils::ResolveScript(Dart_Handle url) {
+  const int kNumArgs = 1;
+  Dart_Handle dart_args[kNumArgs];
+  dart_args[0] = url;
+  return Dart_Invoke(DartUtils::LookupBuiltinLib(),
+                     NewString("_resolveScriptUri"), kNumArgs, dart_args);
+}
+
 static bool CheckMagicNumber(const uint8_t* buffer,
                              intptr_t buffer_length,
                              const MagicNumberData& magic_number) {
@@ -442,6 +465,9 @@
           Dart_SetField(builtin_lib, NewString("_traceLoading"), Dart_True());
       RETURN_IF_ERROR(result);
     }
+    // Set current working directory.
+    result = SetWorkingDirectory();
+    RETURN_IF_ERROR(result);
   }
   return Dart_True();
 }
@@ -488,6 +514,21 @@
                        wait_for_event_handle);
 }
 
+Dart_Handle DartUtils::SetupPackageConfig(const char* packages_config) {
+  Dart_Handle result = Dart_Null();
+
+  if (packages_config != NULL) {
+    result = NewString(packages_config);
+    RETURN_IF_ERROR(result);
+    const int kNumArgs = 1;
+    Dart_Handle dart_args[kNumArgs];
+    dart_args[0] = result;
+    result = Dart_Invoke(DartUtils::LookupBuiltinLib(),
+                         NewString("_setPackagesMap"), kNumArgs, dart_args);
+  }
+  return result;
+}
+
 Dart_Handle DartUtils::PrepareForScriptLoading(bool is_service_isolate,
                                                bool trace_loading) {
   // First ensure all required libraries are available.
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index c2fa094..23122ad 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -161,6 +161,8 @@
   static Dart_Handle MakeUint8Array(const uint8_t* buffer, intptr_t length);
   static Dart_Handle PrepareForScriptLoading(bool is_service_isolate,
                                              bool trace_loading);
+  static Dart_Handle SetupPackageConfig(const char* packages_file);
+
   static Dart_Handle SetupIOLibrary(const char* namespc_path,
                                     const char* script_uri,
                                     bool disable_exit);
@@ -223,6 +225,8 @@
 
   static bool SetOriginalWorkingDirectory();
 
+  static Dart_Handle ResolveScript(Dart_Handle url);
+
   enum MagicNumber {
     kAppJITMagicNumber,
     kKernelMagicNumber,
@@ -261,6 +265,7 @@
   static Dart_Handle EnvironmentCallback(Dart_Handle name);
 
  private:
+  static Dart_Handle SetWorkingDirectory();
   static Dart_Handle PrepareBuiltinLibrary(Dart_Handle builtin_lib,
                                            Dart_Handle internal_lib,
                                            bool is_service_isolate,
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 36e39a5..45b625d 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -240,8 +240,7 @@
 
   return Dart_CompileToKernel(
       sanitized_uri, platform_strong_dill_for_compilation_,
-      platform_strong_dill_for_compilation_size_, incremental, package_config,
-      DartUtils::original_working_directory);
+      platform_strong_dill_for_compilation_size_, incremental, package_config);
 }
 
 void DFE::CompileAndReadScript(const char* script_uri,
diff --git a/runtime/bin/isolate_data.cc b/runtime/bin/isolate_data.cc
index 4fca8c4..1547975 100644
--- a/runtime/bin/isolate_data.cc
+++ b/runtime/bin/isolate_data.cc
@@ -15,6 +15,7 @@
                                    bool isolate_run_app_snapshot)
     : script_url((url != NULL) ? strdup(url) : NULL),
       app_snapshot_(app_snapshot),
+      resolved_packages_config_(NULL),
       kernel_buffer_(NULL),
       kernel_buffer_size_(0),
       isolate_run_app_snapshot_(isolate_run_app_snapshot) {
@@ -28,6 +29,8 @@
   script_url = NULL;
   free(packages_file_);
   packages_file_ = NULL;
+  free(resolved_packages_config_);
+  resolved_packages_config_ = NULL;
   kernel_buffer_ = NULL;
   kernel_buffer_size_ = 0;
 }
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index f218285..6dae87a 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -74,6 +74,18 @@
     kernel_buffer_size_ = size;
   }
 
+  const char* resolved_packages_config() const {
+    return resolved_packages_config_;
+  }
+
+  void set_resolved_packages_config(const char* packages_config) {
+    if (resolved_packages_config_ != NULL) {
+      free(resolved_packages_config_);
+      resolved_packages_config_ = NULL;
+    }
+    resolved_packages_config_ = strdup(packages_config);
+  }
+
   bool RunFromAppSnapshot() const {
     // If the main isolate is using an app snapshot the [app_snapshot_] pointer
     // will be still nullptr (see main.cc:CreateIsolateGroupAndSetupHelper)
@@ -87,6 +99,7 @@
   friend class IsolateData;  // For packages_file_
 
   std::unique_ptr<AppSnapshot> app_snapshot_;
+  char* resolved_packages_config_;
   std::shared_ptr<uint8_t> kernel_buffer_;
   intptr_t kernel_buffer_size_;
   char* packages_file_ = nullptr;
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 5c8c302..6868012 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -23,22 +23,27 @@
 extern DFE dfe;
 #endif
 
-// Initialize package resolution state.
-// Returns the resolved script URI after it resolves 'script_uri' in the
-// current working directory iff the given uri did not specify a scheme
-// (e.g. a path to a script file on the command line).
-Dart_Handle Loader::Init(const char* script_uri, IsolateData* isolate_data) {
+Dart_Handle Loader::InitForSnapshot(const char* snapshot_uri,
+                                    IsolateData* isolate_data) {
   ASSERT(isolate_data != NULL);
-  const char* packages_file = isolate_data->packages_file();
+
+  return Loader::Init(isolate_data->packages_file(),
+                      DartUtils::original_working_directory, snapshot_uri);
+}
+
+// Initialize package resolution state.
+Dart_Handle Loader::Init(const char* packages_file,
+                         const char* working_directory,
+                         const char* root_script_uri) {
   const int kNumArgs = 3;
   Dart_Handle dart_args[kNumArgs];
   dart_args[0] = (packages_file == NULL)
                      ? Dart_Null()
                      : Dart_NewStringFromCString(packages_file);
-  dart_args[1] =
-      Dart_NewStringFromCString(DartUtils::original_working_directory);
-  dart_args[2] = (script_uri == NULL) ? Dart_Null()
-                                      : Dart_NewStringFromCString(script_uri);
+  dart_args[1] = Dart_NewStringFromCString(working_directory);
+  dart_args[2] = (root_script_uri == NULL)
+                     ? Dart_Null()
+                     : Dart_NewStringFromCString(root_script_uri);
   return Dart_Invoke(DartUtils::LookupBuiltinLib(),
                      DartUtils::NewString("_Init"), kNumArgs, dart_args);
 }
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index a346025..f4715e9 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -17,7 +17,8 @@
 
 class Loader {
  public:
-  static Dart_Handle Init(const char* script_uri, IsolateData* isolate_data);
+  static Dart_Handle InitForSnapshot(const char* snapshot_uri,
+                                     IsolateData* isolate_data);
 
   static Dart_Handle ReloadNativeExtensions();
 
@@ -29,6 +30,10 @@
   static void InitOnce();
 
  private:
+  static Dart_Handle Init(const char* packages_file,
+                          const char* working_directory,
+                          const char* root_script_uri);
+
   static Dart_Handle LoadImportExtension(const char* url_string,
                                          Dart_Handle library);
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 4d76a73..e99d675 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -174,8 +174,10 @@
 
 static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate,
                                       IsolateData* isolate_data,
-                                      bool is_isolate_group_start) {
+                                      bool is_isolate_group_start,
+                                      const char** resolved_packages_config) {
   auto isolate_group_data = isolate_data->isolate_group_data();
+  const auto packages_file = isolate_data->packages_file();
   const auto script_uri = isolate_group_data->script_url;
 
   Dart_Handle result;
@@ -186,6 +188,24 @@
   result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
   if (Dart_IsError(result)) return result;
 
+  // Setup packages config if specified.
+  result = DartUtils::SetupPackageConfig(packages_file);
+  if (Dart_IsError(result)) return result;
+  if (!Dart_IsNull(result) && resolved_packages_config != nullptr) {
+    result = Dart_StringToCString(result, resolved_packages_config);
+    if (Dart_IsError(result)) return result;
+    ASSERT(*resolved_packages_config != nullptr);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    if (is_isolate_group_start) {
+      isolate_group_data->set_resolved_packages_config(
+          *resolved_packages_config);
+    } else {
+      ASSERT(strcmp(isolate_group_data->resolved_packages_config(),
+                    *resolved_packages_config) == 0);
+    }
+#endif
+  }
+
   result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback);
   if (Dart_IsError(result)) return result;
 
@@ -215,17 +235,35 @@
   *child_callback_data = isolate_data;
 
   Dart_EnterScope();
-  Dart_Handle resolved_script_uri;
   const auto script_uri = isolate_group_data->script_url;
   const bool isolate_run_app_snapshot =
       isolate_group_data->RunFromAppSnapshot();
   Dart_Handle result = SetupCoreLibraries(isolate, isolate_data,
-                                          /*group_start=*/false);
+                                          /*group_start=*/false,
+                                          /*resolved_packages_config=*/nullptr);
   if (Dart_IsError(result)) goto failed;
 
-  // Resolve script URI and Initialize package resolution state.
-  resolved_script_uri = Loader::Init(script_uri, isolate_data);
-  if (Dart_IsError(resolved_script_uri)) goto failed;
+  if (isolate_run_app_snapshot) {
+    if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
+      result = Loader::InitForSnapshot(script_uri, isolate_data);
+      if (Dart_IsError(result)) goto failed;
+    }
+  } else {
+    result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
+    if (Dart_IsError(result)) return result != nullptr;
+
+    if (isolate_group_data->kernel_buffer().get() != nullptr) {
+      // Various core-library parts will send requests to the Loader to resolve
+      // relative URIs and perform other related tasks. We need Loader to be
+      // initialized for this to work because loading from Kernel binary
+      // bypasses normal source code loading paths that initialize it.
+      const char* resolved_script_uri = NULL;
+      result = Dart_StringToCString(result, &resolved_script_uri);
+      if (Dart_IsError(result)) goto failed;
+      result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
+      if (Dart_IsError(result)) goto failed;
+    }
+  }
 
   if (isolate_run_app_snapshot) {
     result = Loader::ReloadNativeExtensions();
@@ -262,8 +300,10 @@
 
   auto isolate_data = reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
 
+  const char* resolved_packages_config = nullptr;
   result = SetupCoreLibraries(isolate, isolate_data,
-                              /*is_isolate_group_start=*/true);
+                              /*is_isolate_group_start=*/true,
+                              &resolved_packages_config);
   CHECK_RESULT(result);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -287,7 +327,7 @@
     intptr_t application_kernel_buffer_size = 0;
     dfe.CompileAndReadScript(script_uri, &application_kernel_buffer,
                              &application_kernel_buffer_size, error, exit_code,
-                             packages_config);
+                             resolved_packages_config);
     if (application_kernel_buffer == NULL) {
       Dart_ExitScope();
       Dart_ShutdownIsolate();
@@ -298,8 +338,11 @@
     kernel_buffer = application_kernel_buffer;
     kernel_buffer_size = application_kernel_buffer_size;
   }
-  // Load the specified application script into the newly created isolate.
   if (kernel_buffer != NULL) {
+    Dart_Handle uri = Dart_NewStringFromCString(script_uri);
+    CHECK_RESULT(uri);
+    Dart_Handle resolved_script_uri = DartUtils::ResolveScript(uri);
+    CHECK_RESULT(resolved_script_uri);
     result = Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
     CHECK_RESULT(result);
   }
@@ -310,29 +353,47 @@
     CHECK_RESULT(result);
   }
 
-  // Resolve script URI and Initialize package resolution state.
-  Dart_Handle resolved_script_uri = Loader::Init(script_uri, isolate_data);
-  CHECK_RESULT(resolved_script_uri);
-#if !defined(DART_PRECOMPILED_RUNTIME)
   if (isolate_run_app_snapshot) {
+    if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
+      Dart_Handle result = Loader::InitForSnapshot(script_uri, isolate_data);
+      CHECK_RESULT(result);
+    }
+#if !defined(DART_PRECOMPILED_RUNTIME)
     if (is_main_isolate) {
       // Find the canonical uri of the app snapshot. We'll use this to decide if
       // other isolates should use the app snapshot or the core snapshot.
-      const char* resolved_script = NULL;
-      result = Dart_StringToCString(resolved_script_uri, &resolved_script);
+      const char* resolved_script_uri = NULL;
+      result = Dart_StringToCString(
+          DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri)),
+          &resolved_script_uri);
       CHECK_RESULT(result);
       ASSERT(app_script_uri == NULL);
-      app_script_uri = strdup(resolved_script);
+      app_script_uri = strdup(resolved_script_uri);
     }
-  }
-  Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
-                     Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
-                     NULL, NULL);
-#else
-  if (!isolate_run_app_snapshot) {
-    UNREACHABLE();
-  }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    // Load the specified application script into the newly created isolate.
+    Dart_Handle uri =
+        DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
+    CHECK_RESULT(uri);
+    if (kernel_buffer != NULL) {
+      // relative URIs and perform other related tasks. We need Loader to be
+      // initialized for this to work because loading from Kernel binary
+      // bypasses normal source code loading paths that initialize it.
+      const char* resolved_script_uri = NULL;
+      result = Dart_StringToCString(uri, &resolved_script_uri);
+      CHECK_RESULT(result);
+      result = Loader::InitForSnapshot(resolved_script_uri, isolate_data);
+      CHECK_RESULT(result);
+    }
+    Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
+                       Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
+                       NULL, NULL);
+#else
+    UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  }
 
   if (Options::gen_snapshot_kind() == kAppJIT) {
     // If we sort, we must do it for all isolates, not just the main isolate,
@@ -793,9 +854,8 @@
         Options::package_root());
   }
 
-  const char* packages_config = Options::packages_file();
   Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
-      is_main_isolate, script_name, "main", packages_config, &flags,
+      is_main_isolate, script_name, "main", Options::packages_file(), &flags,
       NULL /* callback_data */, &error, &exit_code);
 
   if (isolate == NULL) {
@@ -820,6 +880,8 @@
 
   Dart_EnterScope();
 
+  auto isolate_group_data =
+      reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
   if (Options::gen_snapshot_kind() == kKernel) {
     if (vm_run_app_snapshot) {
       Syslog::PrintErr(
@@ -829,7 +891,7 @@
       Platform::Exit(kErrorExitCode);
     }
     Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
-                             packages_config);
+                             isolate_group_data->resolved_packages_config());
   } else {
     // Lookup the library of the root script.
     Dart_Handle root_lib = Dart_RootLibrary();
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 33b9310..56120e7 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3332,17 +3332,6 @@
  *
  * \param platform_kernel_size The length of the platform_kernel buffer.
  *
- * \param incremental_compile Specifies if incremental compilation is needed.
- *
- * \param package_config Uri of the package configuration file (either in format
- *   of .packages or .dart_tool/package_config.json) for the null safety
- *   detection to resolve package imports against. If this parameter is not
- *   passed the package resolution of the parent isolate should be used.
- *
- * \param original_working_directory current working directory when the VM
- *   process was launched, this is used to correctly resolve the path specified
- *   for package_config.
- *
  * \return Returns the result of the compilation.
  *
  * On a successful compilation the returned [Dart_KernelCompilationResult] has
@@ -3360,8 +3349,7 @@
                      const uint8_t* platform_kernel,
                      const intptr_t platform_kernel_size,
                      bool incremental_compile,
-                     const char* package_config,
-                     const char* original_working_directory);
+                     const char* package_config);
 
 typedef struct {
   const char* uri;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 060963a..b3800b5 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5980,8 +5980,7 @@
                      const uint8_t* platform_kernel,
                      intptr_t platform_kernel_size,
                      bool incremental_compile,
-                     const char* package_config,
-                     const char* original_working_directory) {
+                     const char* package_config) {
   API_TIMELINE_DURATION(Thread::Current());
 
   Dart_KernelCompilationResult result = {};
@@ -5989,9 +5988,9 @@
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = strdup("Dart_CompileToKernel is unsupported.");
 #else
-  result = KernelIsolate::CompileToKernel(
-      script_uri, platform_kernel, platform_kernel_size, 0, NULL,
-      incremental_compile, package_config, original_working_directory);
+  result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
+                                          platform_kernel_size, 0, NULL,
+                                          incremental_compile, package_config);
   if (result.status == Dart_KernelCompilationStatus_Ok) {
     Dart_KernelCompilationResult accept_result =
         KernelIsolate::AcceptCompilation();
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 3fcf437..6c83404 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -1107,7 +1107,7 @@
     TransitionVMToNative transition(Thread::Current());
     retval = KernelIsolate::CompileToKernel(root_lib_url, nullptr, 0,
                                             modified_scripts_count,
-                                            modified_scripts, true);
+                                            modified_scripts, true, nullptr);
   }
   if (retval.status != Dart_KernelCompilationStatus_Ok) {
     if (retval.kernel != nullptr) {
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 96dd335..947d468 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -1001,7 +1001,6 @@
     Dart_SourceFile source_files[],
     bool incremental_compile,
     const char* package_config,
-    const char* original_working_directory,
     const char* multiroot_filepaths,
     const char* multiroot_scheme) {
   // Start the kernel Isolate if it is not already running.
@@ -1027,7 +1026,7 @@
       kCompileTag, kernel_port, script_uri, platform_kernel,
       platform_kernel_size, source_file_count, source_files,
       incremental_compile, package_config, multiroot_filepaths,
-      multiroot_scheme, experimental_flags_, original_working_directory);
+      multiroot_scheme, experimental_flags_, NULL);
 }
 
 bool KernelIsolate::DetectNullSafety(const char* script_uri,
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index 132c18c..fbf31e2 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -51,7 +51,6 @@
       Dart_SourceFile source_files[] = NULL,
       bool incremental_compile = true,
       const char* package_config = NULL,
-      const char* original_working_directory = NULL,
       const char* multiroot_filepaths = NULL,
       const char* multiroot_scheme = NULL);
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index fcff399..bcc7d99 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -326,8 +326,7 @@
   Zone* zone = Thread::Current()->zone();
   Dart_KernelCompilationResult result = KernelIsolate::CompileToKernel(
       url, platform_strong_dill, platform_strong_dill_size, sourcefiles_count,
-      sourcefiles, incrementally, nullptr, nullptr, multiroot_filepaths,
-      multiroot_scheme);
+      sourcefiles, incrementally, NULL, multiroot_filepaths, multiroot_scheme);
   if (result.status == Dart_KernelCompilationStatus_Ok) {
     if (KernelIsolate::AcceptCompilation().status !=
         Dart_KernelCompilationStatus_Ok) {
diff --git a/sdk/lib/_internal/vm/bin/builtin.dart b/sdk/lib/_internal/vm/bin/builtin.dart
index 8dcbadf..5abcbfb 100644
--- a/sdk/lib/_internal/vm/bin/builtin.dart
+++ b/sdk/lib/_internal/vm/bin/builtin.dart
@@ -17,6 +17,10 @@
 // command line.
 bool _traceLoading = false;
 
+// Before handling an embedder entrypoint we finalize the setup of the
+// dart:_builtin library.
+bool _setupCompleted = false;
+
 // 'print' implementation.
 // The standalone embedder registers the closurized _print function with the
 // dart:core library.
@@ -89,6 +93,17 @@
   return fixedPath;
 }
 
+_setPackagesConfig(String packagesParam) {
+  var packagesName = _sanitizeWindowsPath(packagesParam);
+  var packagesUri = Uri.parse(packagesName);
+  if (packagesUri.scheme == '') {
+    // Script does not have a scheme, assume that it is a path,
+    // resolve it against the working directory.
+    packagesUri = _workingDirectory.resolveUri(packagesUri);
+  }
+  _packagesConfigUri = packagesUri;
+}
+
 // Given a uri with a 'package' scheme, return a Uri that is prefixed with
 // the package root or resolved relative to the package configuration.
 Uri _resolvePackageUri(Uri uri) {
@@ -470,53 +485,60 @@
 
 // Embedder Entrypoint:
 // The embedder calls this method to initial the package resolution state.
-// Returns the resolved script URI after it resolves the script uri in the
-// current working directory iff the given uri did not specify a scheme
-// (e.g. a path to a script file on the command line).
 @pragma("vm:entry-point")
-String _Init(
-    String packagesConfig, String workingDirectory, String rootScript) {
-  if (_traceLoading) {
-    _log("_Init: $packagesConfig $workingDirectory $rootScript");
-  }
-
+void _Init(String packagesConfig, String workingDirectory, String rootScript) {
   // Register callbacks and hooks with the rest of core libraries.
   _setupHooks();
 
   // _workingDirectory must be set first.
   _workingDirectory = new Uri.directory(workingDirectory);
-  if (_traceLoading) {
-    _log('_Init (working directory): $_workingDirectory');
-  }
 
   // setup _rootScript.
   if (rootScript != null) {
-    _rootScript = _resolveScriptUri(rootScript);
-    assert(rootScript != null);
+    _rootScript = Uri.parse(rootScript);
   }
 
   // If the --packages flag was passed, setup _packagesConfig.
   if (packagesConfig != null) {
     _packageMap = null;
-    VMLibraryHooks.packageConfigString = _setPackagesConfig(packagesConfig);
+    _setPackagesConfig(packagesConfig);
   }
-
-  if (_traceLoading) {
-    _log("_Init returns: ${rootScript.toString()}");
-  }
-  return _rootScript.toString();
 }
 
-// packagesParam is the value of the --packages command line option.
-// It can point to a ".packages" or a ".dart_tool/package_config.json"
+// Embedder Entrypoint:
+// The embedder calls this method with the current working directory.
+@pragma("vm:entry-point")
+void _setWorkingDirectory(String cwd) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
+  if (_traceLoading) {
+    _log('Setting working directory: $cwd');
+  }
+  _workingDirectory = new Uri.directory(cwd);
+  if (_traceLoading) {
+    _log('Working directory URI: $_workingDirectory');
+  }
+}
+
+// Embedder Entrypoint:
+// The embedder calls this method with the value of the --packages command line
+// option. It can point to a ".packages" or a ".dart_tool/package_config.json"
 // file.
-String _setPackagesConfig(String packagesParam) {
+@pragma("vm:entry-point")
+String _setPackagesMap(String packagesParam) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
   // First convert the packages parameter from the command line to a URI which
   // can be handled by the loader code.
   // TODO(iposva): Consider refactoring the common code below which is almost
   // shared with resolution of the root script.
   if (_traceLoading) {
-    _log("Resolving packages config: $packagesParam");
+    _log("Resolving packages map: $packagesParam");
+  }
+  if (_workingDirectory == null) {
+    throw 'No current working directory set.';
   }
   var packagesName = _sanitizeWindowsPath(packagesParam);
   var packagesUri = Uri.parse(packagesName);
@@ -525,19 +547,24 @@
     // resolve it against the working directory.
     packagesUri = _workingDirectory.resolveUri(packagesUri);
   }
-  _packagesConfigUri = packagesUri;
+  var packagesUriStr = packagesUri.toString();
+  VMLibraryHooks.packageConfigString = packagesUriStr;
   if (_traceLoading) {
-    _log('Resolved packages config to: $packagesUri');
+    _log('Resolved packages map to: $packagesUri');
   }
-  return packagesUri.toString();
+  return packagesUriStr;
 }
 
 // Resolves the script uri in the current working directory iff the given uri
 // did not specify a scheme (e.g. a path to a script file on the command line).
-Uri _resolveScriptUri(String scriptName) {
+@pragma("vm:entry-point")
+String _resolveScriptUri(String scriptName) {
   if (_traceLoading) {
     _log("Resolving script: $scriptName");
   }
+  if (_workingDirectory == null) {
+    throw 'No current working directory set.';
+  }
   scriptName = _sanitizeWindowsPath(scriptName);
 
   var scriptUri = Uri.parse(scriptName);
@@ -547,15 +574,20 @@
     scriptUri = _workingDirectory.resolveUri(scriptUri);
   }
 
+  // Remember the root script URI so that we can resolve packages based on
+  // this location.
+  _rootScript = scriptUri;
+
   if (_traceLoading) {
     _log('Resolved entry point to: $_rootScript');
   }
-  return scriptUri;
+  return scriptUri.toString();
 }
 
 // Register callbacks and hooks with the rest of the core libraries.
 @pragma("vm:entry-point")
 _setupHooks() {
+  _setupCompleted = true;
   VMLibraryHooks.packageConfigUriFuture = _getPackageConfigFuture;
   VMLibraryHooks.resolvePackageUriFuture = _resolvePackageUriFuture;
 }