8
8
#include < stdlib.h>
9
9
#include < string.h>
10
10
11
+ #include < cerrno>
11
12
#include < memory>
12
13
#include < utility>
13
14
35
36
#include " include/dart_api.h"
36
37
#include " include/dart_embedder_api.h"
37
38
#include " include/dart_tools_api.h"
39
+ #include " platform/assert.h"
38
40
#include " platform/globals.h"
39
41
#include " platform/syslog.h"
40
42
#include " platform/utils.h"
@@ -257,8 +259,8 @@ static bool OnIsolateInitialize(void** child_callback_data, char** error) {
257
259
static void * NativeAssetsDlopenRelative (const char * path, char ** error) {
258
260
auto isolate_group_data =
259
261
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);
262
264
}
263
265
264
266
static Dart_Isolate IsolateSetupHelper (Dart_Isolate isolate,
@@ -474,7 +476,8 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
474
476
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
475
477
&isolate_snapshot_data, &isolate_snapshot_instructions);
476
478
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);
478
481
isolate_data = new IsolateData (isolate_group_data);
479
482
isolate = Dart_CreateIsolateGroup (
480
483
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
@@ -492,8 +495,9 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
492
495
intptr_t kernel_service_buffer_size = 0 ;
493
496
dfe.LoadKernelService (&kernel_service_buffer, &kernel_service_buffer_size);
494
497
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);
497
501
isolate_group_data->SetKernelBufferUnowned (
498
502
const_cast <uint8_t *>(kernel_service_buffer),
499
503
kernel_service_buffer_size);
@@ -529,7 +533,8 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
529
533
ASSERT (script_uri != nullptr );
530
534
Dart_Isolate isolate = nullptr ;
531
535
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 );
533
538
ASSERT (flags != nullptr );
534
539
535
540
#if defined(DART_PRECOMPILED_RUNTIME)
@@ -642,9 +647,9 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
642
647
app_snapshot->SetBuffers (
643
648
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
644
649
&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);
648
653
isolate_data = new IsolateData (isolate_group_data);
649
654
isolate = Dart_CreateIsolateGroup (
650
655
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
@@ -664,8 +669,8 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
664
669
delete app_snapshot;
665
670
}
666
671
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);
669
674
uint8_t * application_kernel_buffer = nullptr ;
670
675
intptr_t application_kernel_buffer_size = 0 ;
671
676
dfe.ReadScript (dartdev_path.get (), nullptr , &application_kernel_buffer,
@@ -698,6 +703,7 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
698
703
static Dart_Isolate CreateIsolateGroupAndSetupHelper (
699
704
bool is_main_isolate,
700
705
const char * script_uri,
706
+ const char * asset_resolution_base,
701
707
const char * name,
702
708
const char * packages_config,
703
709
Dart_IsolateFlags* flags,
@@ -778,8 +784,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
778
784
PathSanitizer packages_config_sanitizer (packages_config);
779
785
#endif // !defined(DART_PRECOMPILED_RUNTIME)
780
786
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);
783
790
if (kernel_buffer != nullptr ) {
784
791
isolate_group_data->SetKernelBufferNewlyOwned (kernel_buffer,
785
792
kernel_buffer_size);
@@ -845,6 +852,74 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
845
852
846
853
#undef CHECK_RESULT
847
854
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
+
848
923
static Dart_Isolate CreateIsolateGroupAndSetup (const char * script_uri,
849
924
const char * main,
850
925
const char * package_root,
@@ -895,9 +970,13 @@ static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri,
895
970
}
896
971
897
972
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);
901
980
}
902
981
903
982
static void OnIsolateShutdown (void * isolate_group_data, void * isolate_data) {
@@ -985,6 +1064,7 @@ static void CompileAndSaveKernel(const char* script_name,
985
1064
}
986
1065
987
1066
void RunMainIsolate (const char * script_name,
1067
+ const char * asset_resolution_base,
988
1068
const char * package_config_override,
989
1069
CommandLineOptions* dart_options) {
990
1070
if (script_name != nullptr ) {
@@ -1021,7 +1101,7 @@ void RunMainIsolate(const char* script_name,
1021
1101
flags.snapshot_is_dontneed_safe = dontneed_safe;
1022
1102
1023
1103
Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper (
1024
- /* is_main_isolate */ true , script_name, " main" ,
1104
+ /* is_main_isolate */ true , script_name, asset_resolution_base, " main" ,
1025
1105
Options::packages_file () == nullptr ? package_config_override
1026
1106
: Options::packages_file (),
1027
1107
&flags, nullptr /* callback_data */ , &error, &exit_code);
@@ -1129,6 +1209,7 @@ void main(int argc, char** argv) {
1129
1209
#endif
1130
1210
1131
1211
char * script_name = nullptr ;
1212
+ CStringUniquePtr asset_resolution_base = CStringUniquePtr ();
1132
1213
// Allows the dartdev process to point to the desired package_config.
1133
1214
char * package_config_override = nullptr ;
1134
1215
const int EXTRA_VM_ARGUMENTS = 10 ;
@@ -1215,6 +1296,15 @@ void main(int argc, char** argv) {
1215
1296
if (app_snapshot != nullptr ) {
1216
1297
script_name = argv[0 ];
1217
1298
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
+
1218
1308
// Store the executable name.
1219
1309
Platform::SetExecutableName (argv[0 ]);
1220
1310
@@ -1429,11 +1519,21 @@ void main(int argc, char** argv) {
1429
1519
#endif // !defined(DART_PRECOMPILED_RUNTIME)
1430
1520
1431
1521
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
+ }
1432
1531
if (Options::gen_snapshot_kind () == kKernel ) {
1433
1532
CompileAndSaveKernel (script_name, package_config_override, &dart_options);
1434
1533
} else {
1435
1534
// 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);
1437
1537
}
1438
1538
}
1439
1539
@@ -1453,6 +1553,7 @@ void main(int argc, char** argv) {
1453
1553
if (ran_dart_dev && script_name != nullptr ) {
1454
1554
free (script_name);
1455
1555
}
1556
+ asset_resolution_base.reset ();
1456
1557
1457
1558
// Free copied argument strings if converted.
1458
1559
if (argv_converted) {
0 commit comments