88#include < stdlib.h>
99#include < string.h>
1010
11+ #include < cerrno>
1112#include < memory>
1213#include < utility>
1314
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) {
257259static 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
264266static 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,
698703static 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+
848923static 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
903982static void OnIsolateShutdown (void * isolate_group_data, void * isolate_data) {
@@ -985,6 +1064,7 @@ static void CompileAndSaveKernel(const char* script_name,
9851064}
9861065
9871066void 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