Skip to content

Commit 592e5c1

Browse files
dcharkesCommit Queue
authored andcommitted
[native assets] Support PATHEXT invocations with appended snapshot
This CL introduces an `IsolateData::asset_base_path` which contains the fully resolved base path used for assets which are loaded with a relative path. (Resolving both PATHEXT and symlinks.) The asset base path is now only resolved once, instead of on every relative asset load. The asset base path is now eagerly resolved. To prevent existing error messages for files not existing changing in `dartdev` and `Isolate.spawnUri`, files not existing errors are ignored. To prevent `tests/standalone/io/named_pipe_script_test.dart` from failing, failing to canonicalize a file path is treated as no asset base path rather than reporting a failure. TEST=pkg/dartdev/test/native_assets/*.dart Bug: #60946 Change-Id: I79a9144d220dfb3e54311725d41f8f91c88db3a1 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-linux-release-try,pkg-mac-release-try,pkg-mac-release-arm64-try,pkg-win-release-arm64-try,pkg-win-release-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-android-release-arm64c-try,vm-aot-linux-debug-x64-try,vm-aot-mac-debug-arm64-try,vm-aot-win-debug-arm64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-msan-linux-release-x64-try,vm-asan-linux-release-x64-try,vm-linux-release-x64-try,vm-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/435421 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 86df26d commit 592e5c1

File tree

10 files changed

+185
-113
lines changed

10 files changed

+185
-113
lines changed

pkg/dartdev/test/native_assets/build_test.dart

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,15 @@ void main([List<String> args = const []]) async {
6666
final link = Link.fromUri(
6767
tempUri.resolve(OS.current.executableFileName('my_link')));
6868
await link.create(absoluteExeUri.toFilePath());
69-
if (OS.current == OS.windows) {
70-
for (final exeUri in [
71-
removeDotExe(link.uri),
72-
removeDotExe(absoluteExeUri),
73-
removeDotExe(relativeExeUri),
74-
]) {
75-
final result = await runProcess(
76-
executable: exeUri,
77-
arguments: [],
78-
workingDirectory: dartAppUri,
79-
logger: logger,
80-
);
81-
// TODO(https://dartbug.com/60946): Support PATHEXT.
82-
expect(result.exitCode, isNot(0));
83-
expect(
84-
result.stderr,
85-
stringContainsInOrder(
86-
[
87-
'Failed to canonicalize the script uri',
88-
'The system cannot find the file specified.',
89-
],
90-
),
91-
);
92-
}
93-
}
9469
for (final exeUri in [
9570
absoluteExeUri,
9671
relativeExeUri,
9772
link.uri,
73+
if (OS.current == OS.windows) ...[
74+
removeDotExe(absoluteExeUri),
75+
removeDotExe(relativeExeUri),
76+
removeDotExe(link.uri),
77+
]
9878
]) {
9979
final result = await runProcess(
10080
executable: exeUri,

runtime/bin/analyze_snapshot.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ int RunAnalyzer(int argc, char** argv) {
213213
}
214214

215215
auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
216-
new IsolateGroupData(nullptr, nullptr, nullptr, false));
216+
new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false));
217217

218218
Dart_IsolateFlags isolate_flags;
219219
Dart_IsolateFlagsInitialize(&isolate_flags);

runtime/bin/gen_snapshot.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
746746
}
747747

748748
auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
749-
new IsolateGroupData(nullptr, nullptr, nullptr, false));
749+
new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false));
750750
Dart_Isolate isolate;
751751
char* error = nullptr;
752752

runtime/bin/isolate_data.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ namespace dart {
1010
namespace bin {
1111

1212
IsolateGroupData::IsolateGroupData(const char* url,
13+
const char* asset_resolution_base,
1314
const char* packages_file,
1415
AppSnapshot* app_snapshot,
1516
bool isolate_run_app_snapshot)
1617
: script_url((url != nullptr) ? Utils::StrDup(url) : nullptr),
18+
asset_resolution_base((asset_resolution_base != nullptr)
19+
? Utils::StrDup(asset_resolution_base)
20+
: nullptr),
1721
app_snapshot_(app_snapshot),
1822
resolved_packages_config_(nullptr),
1923
kernel_buffer_(nullptr),
@@ -29,6 +33,7 @@ IsolateGroupData::~IsolateGroupData() {
2933
delete loading_units_[i];
3034
}
3135
free(script_url);
36+
free(asset_resolution_base);
3237
script_url = nullptr;
3338
free(packages_file_);
3439
packages_file_ = nullptr;

runtime/bin/isolate_data.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,21 @@ class Loader;
3636
class IsolateGroupData {
3737
public:
3838
IsolateGroupData(const char* url,
39+
const char* asset_resolution_base,
3940
const char* packages_file,
4041
AppSnapshot* app_snapshot,
4142
bool isolate_run_app_snapshot);
4243
~IsolateGroupData();
4344

4445
char* script_url;
4546

47+
// Base path for resolving assets with a relative path.
48+
//
49+
// This must be an absolute path pointing to a real file (not a symlink).
50+
//
51+
// May be nullptr.
52+
char* asset_resolution_base;
53+
4654
const std::shared_ptr<uint8_t>& kernel_buffer() const {
4755
return kernel_buffer_;
4856
}

runtime/bin/main_impl.cc

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdlib.h>
99
#include <string.h>
1010

11+
#include <cerrno>
1112
#include <memory>
1213
#include <utility>
1314

@@ -35,6 +36,7 @@
3536
#include "include/dart_api.h"
3637
#include "include/dart_embedder_api.h"
3738
#include "include/dart_tools_api.h"
39+
#include "platform/assert.h"
3840
#include "platform/globals.h"
3941
#include "platform/syslog.h"
4042
#include "platform/utils.h"
@@ -257,8 +259,8 @@ static bool OnIsolateInitialize(void** child_callback_data, char** error) {
257259
static void* NativeAssetsDlopenRelative(const char* path, char** error) {
258260
auto isolate_group_data =
259261
reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
260-
const char* script_uri = isolate_group_data->script_url;
261-
return NativeAssets::DlopenRelative(path, script_uri, error);
262+
return NativeAssets::DlopenRelative(
263+
path, isolate_group_data->asset_resolution_base, error);
262264
}
263265

264266
static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
@@ -474,7 +476,8 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
474476
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
475477
&isolate_snapshot_data, &isolate_snapshot_instructions);
476478
isolate_group_data = new IsolateGroupData(
477-
uri, packages_config, app_snapshot, isolate_run_app_snapshot);
479+
uri, /*asset_resolution_base=*/nullptr, packages_config, app_snapshot,
480+
isolate_run_app_snapshot);
478481
isolate_data = new IsolateData(isolate_group_data);
479482
isolate = Dart_CreateIsolateGroup(
480483
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
@@ -492,8 +495,9 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
492495
intptr_t kernel_service_buffer_size = 0;
493496
dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size);
494497
ASSERT(kernel_service_buffer != nullptr);
495-
isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr,
496-
isolate_run_app_snapshot);
498+
isolate_group_data = new IsolateGroupData(
499+
uri, /*asset_resolution_base=*/nullptr, packages_config, nullptr,
500+
isolate_run_app_snapshot);
497501
isolate_group_data->SetKernelBufferUnowned(
498502
const_cast<uint8_t*>(kernel_service_buffer),
499503
kernel_service_buffer_size);
@@ -529,7 +533,8 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
529533
ASSERT(script_uri != nullptr);
530534
Dart_Isolate isolate = nullptr;
531535
auto isolate_group_data =
532-
new IsolateGroupData(script_uri, packages_config, nullptr, false);
536+
new IsolateGroupData(script_uri, /*asset_resolution_base=*/nullptr,
537+
packages_config, nullptr, false);
533538
ASSERT(flags != nullptr);
534539

535540
#if defined(DART_PRECOMPILED_RUNTIME)
@@ -642,9 +647,9 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
642647
app_snapshot->SetBuffers(
643648
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
644649
&isolate_snapshot_data, &isolate_snapshot_instructions);
645-
isolate_group_data =
646-
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config,
647-
app_snapshot, isolate_run_app_snapshot);
650+
isolate_group_data = new IsolateGroupData(
651+
DART_DEV_ISOLATE_NAME, /*asset_resolution_base=*/nullptr,
652+
packages_config, app_snapshot, isolate_run_app_snapshot);
648653
isolate_data = new IsolateData(isolate_group_data);
649654
isolate = Dart_CreateIsolateGroup(
650655
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
@@ -664,8 +669,8 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
664669
delete app_snapshot;
665670
}
666671
isolate_group_data =
667-
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
668-
isolate_run_app_snapshot);
672+
new IsolateGroupData(DART_DEV_ISOLATE_NAME, nullptr, packages_config,
673+
nullptr, isolate_run_app_snapshot);
669674
uint8_t* application_kernel_buffer = nullptr;
670675
intptr_t application_kernel_buffer_size = 0;
671676
dfe.ReadScript(dartdev_path.get(), nullptr, &application_kernel_buffer,
@@ -698,6 +703,7 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
698703
static Dart_Isolate CreateIsolateGroupAndSetupHelper(
699704
bool is_main_isolate,
700705
const char* script_uri,
706+
const char* asset_resolution_base,
701707
const char* name,
702708
const char* packages_config,
703709
Dart_IsolateFlags* flags,
@@ -778,8 +784,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
778784
PathSanitizer packages_config_sanitizer(packages_config);
779785
#endif // !defined(DART_PRECOMPILED_RUNTIME)
780786

781-
auto isolate_group_data = new IsolateGroupData(
782-
script_uri, packages_config, app_snapshot, isolate_run_app_snapshot);
787+
auto isolate_group_data =
788+
new IsolateGroupData(script_uri, asset_resolution_base, packages_config,
789+
app_snapshot, isolate_run_app_snapshot);
783790
if (kernel_buffer != nullptr) {
784791
isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer,
785792
kernel_buffer_size);
@@ -845,6 +852,74 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
845852

846853
#undef CHECK_RESULT
847854

855+
static CStringUniquePtr ResolveSymlinks(const char* path, char** error) {
856+
auto file_type = File::GetType(nullptr, path, /*follow_links=*/true);
857+
switch (file_type) {
858+
case File::kIsLink:
859+
UNREACHABLE();
860+
case File::kIsSock:
861+
case File::kIsPipe:
862+
// Don't use pipes or sockets as base paths for assets resolution.
863+
return CStringUniquePtr();
864+
case File::kDoesNotExist:
865+
// Don't try to resolve symlinks if the file doesn't exist.
866+
// `dartdev` and `Isolate.spawnUri` will already issue an error.
867+
return CStringUniquePtr();
868+
case File::kIsFile:
869+
case File::kIsDirectory:
870+
break;
871+
}
872+
873+
const size_t kPathBufSize = PATH_MAX + 1;
874+
char canon_path[kPathBufSize];
875+
auto result = File::GetCanonicalPath(nullptr, path, canon_path, kPathBufSize);
876+
if (result == nullptr) {
877+
OSError os_error;
878+
*error = Utils::SCreate(
879+
"Failed to canonicalize path '%s'. OS error: '%s' (%i).\n", path,
880+
os_error.message(), os_error.code());
881+
return CStringUniquePtr();
882+
}
883+
return CStringUniquePtr(Utils::StrDup(canon_path));
884+
}
885+
886+
// Get a file path from the script uri if it is a file uri and resolve symlinks.
887+
static CStringUniquePtr FindAssetResolutionBase(const char* script_uri,
888+
char** error) {
889+
static const char* data_schema = "data:";
890+
static const int data_schema_length = 5;
891+
static const char* package_scheme = "package:";
892+
static const int package_scheme_length = 8;
893+
static const char* https_scheme = "https://";
894+
static const int https_scheme_length = 8;
895+
static const char* http_scheme = "http://";
896+
static const int http_scheme_length = 7;
897+
static const char* file_schema = "file://";
898+
static const int file_schema_length = 7;
899+
900+
if ((strlen(script_uri) > data_schema_length &&
901+
strncmp(script_uri, data_schema, data_schema_length) == 0) ||
902+
(strlen(script_uri) > data_schema_length &&
903+
strncmp(script_uri, package_scheme, package_scheme_length) == 0) ||
904+
(strlen(script_uri) > package_scheme_length &&
905+
strncmp(script_uri, https_scheme, https_scheme_length) == 0) ||
906+
(strlen(script_uri) > http_scheme_length &&
907+
strncmp(script_uri, http_scheme, http_scheme_length) == 0)) {
908+
// No base path for assets.
909+
return CStringUniquePtr();
910+
}
911+
912+
if (strlen(script_uri) > file_schema_length &&
913+
strncmp(script_uri, file_schema, file_schema_length) == 0) {
914+
// Isolate.spawnUri sets a `source` including the file schema,
915+
// e.g. Isolate.spawnUri may make the embedder pass a file:// uri.
916+
return ResolveSymlinks(File::UriToPath(script_uri).get(), error);
917+
}
918+
919+
// It's possible to spawn uri without a scheme, assume file path.
920+
return ResolveSymlinks(script_uri, error);
921+
}
922+
848923
static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
849924
const char* main,
850925
const char* package_root,
@@ -895,9 +970,13 @@ static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
895970
}
896971

897972
bool is_main_isolate = false;
898-
return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main,
899-
package_config, flags, callback_data,
900-
error, &exit_code);
973+
auto asset_resolution_base = FindAssetResolutionBase(script_uri, error);
974+
if (*error != nullptr) {
975+
return nullptr;
976+
}
977+
return CreateIsolateGroupAndSetupHelper(
978+
is_main_isolate, script_uri, asset_resolution_base.get(), main,
979+
package_config, flags, callback_data, error, &exit_code);
901980
}
902981

903982
static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
@@ -985,6 +1064,7 @@ static void CompileAndSaveKernel(const char* script_name,
9851064
}
9861065

9871066
void RunMainIsolate(const char* script_name,
1067+
const char* asset_resolution_base,
9881068
const char* package_config_override,
9891069
CommandLineOptions* dart_options) {
9901070
if (script_name != nullptr) {
@@ -1021,7 +1101,7 @@ void RunMainIsolate(const char* script_name,
10211101
flags.snapshot_is_dontneed_safe = dontneed_safe;
10221102

10231103
Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
1024-
/* is_main_isolate */ true, script_name, "main",
1104+
/* is_main_isolate */ true, script_name, asset_resolution_base, "main",
10251105
Options::packages_file() == nullptr ? package_config_override
10261106
: Options::packages_file(),
10271107
&flags, nullptr /* callback_data */, &error, &exit_code);
@@ -1129,6 +1209,7 @@ void main(int argc, char** argv) {
11291209
#endif
11301210

11311211
char* script_name = nullptr;
1212+
CStringUniquePtr asset_resolution_base = CStringUniquePtr();
11321213
// Allows the dartdev process to point to the desired package_config.
11331214
char* package_config_override = nullptr;
11341215
const int EXTRA_VM_ARGUMENTS = 10;
@@ -1215,6 +1296,15 @@ void main(int argc, char** argv) {
12151296
if (app_snapshot != nullptr) {
12161297
script_name = argv[0];
12171298

1299+
char* error = nullptr;
1300+
asset_resolution_base = ResolveSymlinks(executable_path, &error);
1301+
if (error != nullptr) {
1302+
Syslog::PrintErr("%s", error);
1303+
free(error);
1304+
delete app_snapshot;
1305+
Platform::Exit(kErrorExitCode);
1306+
}
1307+
12181308
// Store the executable name.
12191309
Platform::SetExecutableName(argv[0]);
12201310

@@ -1429,11 +1519,21 @@ void main(int argc, char** argv) {
14291519
#endif // !defined(DART_PRECOMPILED_RUNTIME)
14301520

14311521
if (should_run_user_program) {
1522+
if (asset_resolution_base.get() == nullptr) {
1523+
asset_resolution_base = ResolveSymlinks(script_name, &error);
1524+
if (error != nullptr) {
1525+
Syslog::PrintErr("%s", error);
1526+
free(error);
1527+
delete app_snapshot;
1528+
Platform::Exit(kErrorExitCode);
1529+
}
1530+
}
14321531
if (Options::gen_snapshot_kind() == kKernel) {
14331532
CompileAndSaveKernel(script_name, package_config_override, &dart_options);
14341533
} else {
14351534
// Run the main isolate until we aren't told to restart.
1436-
RunMainIsolate(script_name, package_config_override, &dart_options);
1535+
RunMainIsolate(script_name, asset_resolution_base.get(),
1536+
package_config_override, &dart_options);
14371537
}
14381538
}
14391539

@@ -1453,6 +1553,7 @@ void main(int argc, char** argv) {
14531553
if (ran_dart_dev && script_name != nullptr) {
14541554
free(script_name);
14551555
}
1556+
asset_resolution_base.reset();
14561557

14571558
// Free copied argument strings if converted.
14581559
if (argv_converted) {

0 commit comments

Comments
 (0)