diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart index 6992f5dd5b4..93259492aa7 100644 --- a/pkg/dartdev/lib/src/commands/run.dart +++ b/pkg/dartdev/lib/src/commands/run.dart @@ -550,6 +550,7 @@ See https://dart.dev/to/package-descriptors for more details.''', verbose) { log.stderr(e.message); return errorExitCode; } + DartExecutableWithPackageConfig executableOriginal = executable; if (useResidentCompiler) { final File? residentCompilerInfoFile = @@ -616,6 +617,9 @@ See https://dart.dev/to/package-descriptors for more details.''', verbose) { packageConfigOverride: args.option('packages') ?? executable.packageConfig, useExecProcess: true, + scriptUriOverride: identical(executable, executableOriginal) + ? null + : executableOriginal.executable, ); return 0; } diff --git a/pkg/dartdev/lib/src/vm_interop_handler.dart b/pkg/dartdev/lib/src/vm_interop_handler.dart index 20367a0e4e9..a3814aac899 100644 --- a/pkg/dartdev/lib/src/vm_interop_handler.dart +++ b/pkg/dartdev/lib/src/vm_interop_handler.dart @@ -34,6 +34,11 @@ abstract class VmInteropHandler { // See https://github.com/dart-lang/sdk/issues/53576 bool markMainIsolateAsSystemIsolate = false, bool useExecProcess = false, + + /// When [useExecProcess] pass this path to signal that it originates from + /// another file. Used for launching from a dill file while behaving as if + /// launched directly from a dart file. + String? scriptUriOverride, }) { List argsList; if (useExecProcess && Platform.isWindows) { @@ -45,6 +50,12 @@ abstract class VmInteropHandler { // Escape paths that may contain spaces script = '"$script"'; } + if (scriptUriOverride != null && + scriptUriOverride.contains(' ') && + !scriptUriOverride.contains('"')) { + // Escape paths that may contain spaces + scriptUriOverride = '"$scriptUriOverride"'; + } argsList = [ for (int i = 0; i < args.length; i++) _windowsArgumentEscape(args[i]), ]; @@ -57,6 +68,7 @@ abstract class VmInteropHandler { final message = [ useExecProcess ? _kResultRunExec : _kResultRun, script, + if (useExecProcess) scriptUriOverride, packageConfigOverride, markMainIsolateAsSystemIsolate, argsList, diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart index 800bbb4bd13..7bf617d77f0 100644 --- a/pkg/dartdev/test/commands/run_test.dart +++ b/pkg/dartdev/test/commands/run_test.dart @@ -972,6 +972,95 @@ Future main() async { expect(result.exitCode, 0); }); + test( + 'resident compiler invocation has working Platform.script', + () async { + p = project(name: 'foo'); + p.file('pubspec.yaml', ''' +name: foo +environment: + sdk: '>=2.12.0<3.0.0' +'''); + p.file('bin/script1.dart', r''' +import "dart:io"; +import "dart:isolate"; + +Future main() async { + print("Script1: ${Platform.script}"); + var exitPort = ReceivePort(); + var isolate = await Isolate.spawn( + entryPoint, + "", + onExit: exitPort.sendPort, + ); + await exitPort.first; + + exitPort = ReceivePort(); + await Isolate.spawnUri( + Uri.parse("script2.dart"), + [], + "", + onExit: exitPort.sendPort, + ); + await exitPort.first; +} + +void entryPoint(String arg) { + print(" -> ${Platform.script}"); +} +'''); + p.file('bin/script2.dart', r''' +import "dart:io"; +import "dart:isolate"; + +Future main() async { + print("Script2: ${Platform.script}"); + var exitPort = ReceivePort(); + var isolate = await Isolate.spawn( + entryPoint, + "", + onExit: exitPort.sendPort, + ); + await exitPort.first; +} + +void entryPoint(String arg) { + print(" -> ${Platform.script}"); +} +'''); + + var script1 = File(path.join(p.dir.path, 'bin/script1.dart')); + expect(script1.existsSync(), true); + var script2 = File(path.join(p.dir.path, 'bin/script2.dart')); + expect(script2.existsSync(), true); + + ProcessResult pubGetResult = await p.run(['pub', 'get']); + expect(pubGetResult.stderr, isEmpty); + expect(pubGetResult.exitCode, 0); + + ProcessResult result = await p.run([ + 'run', + '--resident', + '--$residentCompilerInfoFileOption=$serverInfoFile', + 'bin/script1.dart', + ]); + + String stdout = result.stdout.toString().trim(); + expect( + stdout, + ''' +Script1: ${script1.uri} + -> ${script1.uri} +Script2: ${script2.uri} + -> ${script2.uri} +''' + .trim(), + ); + expect(result.stderr, isEmpty); + expect(result.exitCode, 0); + }, + ); + test( 'passing --resident is a prerequisite for passing --resident-compiler-info-file', () async { diff --git a/runtime/bin/dartdev.cc b/runtime/bin/dartdev.cc index 7414303cd73..0083656ab43 100644 --- a/runtime/bin/dartdev.cc +++ b/runtime/bin/dartdev.cc @@ -606,33 +606,48 @@ class DartDev { Syslog::PrintErr("Unable to locate the Dart VM executable"); Platform::Exit(kErrorExitCode); } + ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kString); + + // scriptUriOverride. auto item2 = GetArrayItem(message, 2); ASSERT(item2->type == Dart_CObject_kString || item2->type == Dart_CObject_kNull); + // packageConfigOverride. + auto item3 = GetArrayItem(message, 3); + + ASSERT(item3->type == Dart_CObject_kString || + item3->type == Dart_CObject_kNull); + package_config_override_ = nullptr; - if (item2->type == Dart_CObject_kString) { - package_config_override_ = Utils::StrDup(item2->value.as_string); + if (item3->type == Dart_CObject_kString) { + package_config_override_ = Utils::StrDup(item3->value.as_string); } - intptr_t num_vm_options = dart_vm_options_->count(); - const char** vm_options = dart_vm_options_->arguments(); - ASSERT(GetArrayItem(message, 4)->type == Dart_CObject_kArray); - Dart_CObject* args = GetArrayItem(message, 4); + // markMainIsolateAsSystemIsolate + auto item4 = GetArrayItem(message, 4); + ASSERT(item4->type == Dart_CObject_kBool); + const bool mark_main_isolate_as_system_isolate = item4->value.as_bool; + + // argsList + ASSERT(GetArrayItem(message, 5)->type == Dart_CObject_kArray); + Dart_CObject* args = GetArrayItem(message, 5); intptr_t argc = args->value.as_array.length; Dart_CObject** dart_args = args->value.as_array.values; - auto item3 = GetArrayItem(message, 3); - ASSERT(item3->type == Dart_CObject_kBool); - const bool mark_main_isolate_as_system_isolate = item3->value.as_bool; + auto deleter = [](char** args) { for (intptr_t i = 0; i < argc_; ++i) { free(args[i]); } delete[] args; }; + + intptr_t num_vm_options = dart_vm_options_->count(); + const char** vm_options = dart_vm_options_->arguments(); + // Total count of arguments to be passed to the script being execed. if (mark_main_isolate_as_system_isolate) { argc_ = argc + num_vm_options + 5; @@ -642,6 +657,9 @@ class DartDev { if (package_config_override_ != nullptr) { argc_++; } + if (item2->type == Dart_CObject_kString) { + argc_++; + } // Array of arguments to be passed to the script being execed. argv_ = std::unique_ptr(new char*[argc_ + 1], @@ -697,6 +715,19 @@ class DartDev { argv_[idx++] = Utils::SCreate("--packages=%s", package_config_override_); #endif } + + if (item2->value.as_string != nullptr) { +#if defined(DART_HOST_OS_WINDOWS) + char* script_uri_override = + Utils::SCreate("--script_uri_override=%s", item2->value.as_string); + argv_[idx++] = StringUtilsWin::ArgumentEscape(script_uri_override); + free(script_uri_override); +#else + argv_[idx++] = + Utils::SCreate("--script_uri_override=%s", item2->value.as_string); +#endif + } + // Copy in name of the script to run. argv_[idx++] = Utils::StrDup(GetArrayItem(message, 1)->value.as_string); // Copy in the dart options that need to be passed to the script. diff --git a/runtime/bin/main_impl.cc b/runtime/bin/main_impl.cc index 2624ada981d..31d52281e44 100644 --- a/runtime/bin/main_impl.cc +++ b/runtime/bin/main_impl.cc @@ -690,9 +690,12 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper( PathSanitizer packages_config_sanitizer(packages_config); #endif // !defined(DART_PRECOMPILED_RUNTIME) - auto isolate_group_data = - new IsolateGroupData(script_uri, asset_resolution_base, packages_config, - app_snapshot, isolate_run_app_snapshot); + auto isolate_group_data = new IsolateGroupData( + is_main_isolate && Options::script_uri_override() != nullptr + ? Options::script_uri_override() + : script_uri, + asset_resolution_base, packages_config, app_snapshot, + isolate_run_app_snapshot); if (kernel_buffer != nullptr) { isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer, kernel_buffer_size); diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h index c58c8010608..d6ab3af2026 100644 --- a/runtime/bin/main_options.h +++ b/runtime/bin/main_options.h @@ -31,6 +31,7 @@ namespace bin { V(executable_name, executable_name) \ V(resolved_executable_name, resolved_executable_name) \ V(load_module_snapshot, load_module_snapshot) \ + V(script_uri_override, script_uri_override) \ /* The purpose of these flags is documented in */ \ /* pkg/dartdev/lib/src/commands/compilation_server.dart. */ \ V(resident_server_info_file, resident_server_info_file_path) \