diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index eb4012246fa..568fa5f570c 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -670,7 +670,7 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) { } auto isolate_group_data = std::unique_ptr( - new IsolateGroupData(nullptr, nullptr, nullptr, false)); + new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false)); Dart_Isolate isolate; char* error = NULL; diff --git a/runtime/bin/isolate_data.cc b/runtime/bin/isolate_data.cc index 154797507aa..3bf497c7e63 100644 --- a/runtime/bin/isolate_data.cc +++ b/runtime/bin/isolate_data.cc @@ -10,16 +10,21 @@ namespace dart { namespace bin { IsolateGroupData::IsolateGroupData(const char* url, + const char* package_root, const char* packages_file, AppSnapshot* app_snapshot, bool isolate_run_app_snapshot) : script_url((url != NULL) ? strdup(url) : NULL), + package_root(NULL), app_snapshot_(app_snapshot), resolved_packages_config_(NULL), kernel_buffer_(NULL), kernel_buffer_size_(0), isolate_run_app_snapshot_(isolate_run_app_snapshot) { - if (packages_file != NULL) { + if (package_root != NULL) { + ASSERT(packages_file == NULL); + package_root = strdup(package_root); + } else if (packages_file != NULL) { packages_file_ = strdup(packages_file); } } @@ -27,6 +32,8 @@ IsolateGroupData::IsolateGroupData(const char* url, IsolateGroupData::~IsolateGroupData() { free(script_url); script_url = NULL; + free(package_root); + package_root = NULL; free(packages_file_); packages_file_ = NULL; free(resolved_packages_config_); diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h index 6dae87a3842..c4523a1d742 100644 --- a/runtime/bin/isolate_data.h +++ b/runtime/bin/isolate_data.h @@ -34,12 +34,14 @@ class Loader; class IsolateGroupData { public: IsolateGroupData(const char* url, + const char* package_root, const char* packages_file, AppSnapshot* app_snapshot, bool isolate_run_app_snapshot); ~IsolateGroupData(); char* script_url; + char* package_root; const std::shared_ptr& kernel_buffer() const { return kernel_buffer_; diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 06b91091176..ac3baa542ae 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -180,7 +180,7 @@ static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate, // Prepare builtin and other core libraries for use to resolve URIs. // Set up various closures, e.g: printing, timers etc. - // Set up package configuration for URI resolution. + // Set up 'package root' for URI resolution. result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading()); if (Dart_IsError(result)) return result; @@ -417,6 +417,7 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate, // For now we only support the kernel isolate coming up from an // application snapshot or from a .dill file. static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, + const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, char** error, @@ -458,8 +459,9 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, app_snapshot->SetBuffers( &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions, &isolate_snapshot_data, &isolate_snapshot_instructions); - isolate_group_data = new IsolateGroupData( - uri, packages_config, app_snapshot, isolate_run_app_snapshot); + isolate_group_data = + new IsolateGroupData(uri, package_root, packages_config, app_snapshot, + isolate_run_app_snapshot); isolate_data = new IsolateData(isolate_group_data); isolate = Dart_CreateIsolateGroup( DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, @@ -477,8 +479,8 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, intptr_t kernel_service_buffer_size = 0; dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size); ASSERT(kernel_service_buffer != NULL); - isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr, - isolate_run_app_snapshot); + isolate_group_data = new IsolateGroupData( + uri, package_root, packages_config, nullptr, isolate_run_app_snapshot); isolate_group_data->SetKernelBufferUnowned( const_cast(kernel_service_buffer), kernel_service_buffer_size); @@ -506,6 +508,7 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri, // For now we only support the service isolate coming up from sources // which are compiled by the VM parser. static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, + const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, char** error, @@ -513,8 +516,8 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, #if !defined(PRODUCT) ASSERT(script_uri != NULL); Dart_Isolate isolate = NULL; - auto isolate_group_data = - new IsolateGroupData(script_uri, packages_config, nullptr, false); + auto isolate_group_data = new IsolateGroupData( + script_uri, package_root, packages_config, nullptr, false); #if defined(DART_PRECOMPILED_RUNTIME) // AOT: All isolates start from the app snapshot. @@ -577,6 +580,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper( bool is_main_isolate, const char* script_uri, const char* name, + const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, void* callback_data, @@ -633,8 +637,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper( } #endif // !defined(DART_PRECOMPILED_RUNTIME) - auto isolate_group_data = new IsolateGroupData( - script_uri, packages_config, app_snapshot, isolate_run_app_snapshot); + auto isolate_group_data = + new IsolateGroupData(script_uri, package_root, packages_config, + app_snapshot, isolate_run_app_snapshot); if (kernel_buffer != NULL) { if (parent_kernel_buffer) { isolate_group_data->SetKernelBufferAlreadyOwned( @@ -711,22 +716,28 @@ static Dart_Isolate CreateIsolateGroupAndSetup(const char* script_uri, // The VM should never call the isolate helper with a NULL flags. ASSERT(flags != NULL); ASSERT(flags->version == DART_FLAGS_CURRENT_VERSION); - ASSERT(package_root == nullptr); + if ((package_root != NULL) && (package_config != NULL)) { + *error = strdup( + "Invalid arguments - Cannot simultaneously specify " + "package root and package map."); + return NULL; + } + int exit_code = 0; #if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) { - return CreateAndSetupKernelIsolate(script_uri, package_config, flags, error, - &exit_code); + return CreateAndSetupKernelIsolate(script_uri, package_root, package_config, + flags, error, &exit_code); } #endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) { - return CreateAndSetupServiceIsolate(script_uri, package_config, flags, - error, &exit_code); + return CreateAndSetupServiceIsolate( + script_uri, package_root, package_config, flags, error, &exit_code); } bool is_main_isolate = false; return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main, - package_config, flags, callback_data, - error, &exit_code); + package_root, package_config, flags, + callback_data, error, &exit_code); } static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) { @@ -834,15 +845,10 @@ bool RunMainIsolate(const char* script_name, CommandLineOptions* dart_options) { Dart_IsolateFlags flags; Dart_IsolateFlagsInitialize(&flags); - if (Options::package_root() != nullptr) { - Syslog::PrintErr( - "Warning: The --package-root option is deprecated (was: %s)\n", - Options::package_root()); - } - Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper( - is_main_isolate, script_name, "main", Options::packages_file(), &flags, - NULL /* callback_data */, &error, &exit_code); + is_main_isolate, script_name, "main", Options::package_root(), + Options::packages_file(), &flags, NULL /* callback_data */, &error, + &exit_code); if (isolate == NULL) { Syslog::PrintErr("%s\n", error); diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc index c7b4df64f88..5e44275b9d5 100644 --- a/runtime/bin/run_vm_tests.cc +++ b/runtime/bin/run_vm_tests.cc @@ -101,6 +101,7 @@ static void PrintUsage() { } static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, + const char* package_root, const char* packages_config, Dart_IsolateFlags* flags, char** error) { @@ -116,7 +117,7 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, ASSERT(script_uri != nullptr); Dart_Isolate isolate = nullptr; auto isolate_group_data = new bin::IsolateGroupData( - script_uri, packages_config, /*app_snapshot=*/nullptr, + script_uri, package_root, packages_config, /*app_snapshot=*/nullptr, /*isolate_run_app_snapshot=*/false); const uint8_t* kernel_buffer = nullptr; @@ -168,10 +169,9 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, void* data, char** error) { ASSERT(script_uri != nullptr); - ASSERT(package_root == nullptr); if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) { - return CreateAndSetupServiceIsolate(script_uri, packages_config, flags, - error); + return CreateAndSetupServiceIsolate(script_uri, package_root, + packages_config, flags, error); } const bool is_kernel_isolate = strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0; @@ -200,8 +200,9 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, app_snapshot->SetBuffers( &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions, &isolate_snapshot_data, &isolate_snapshot_instructions); - isolate_group_data = new bin::IsolateGroupData( - script_uri, packages_config, app_snapshot, app_snapshot != nullptr); + isolate_group_data = + new bin::IsolateGroupData(script_uri, package_root, packages_config, + app_snapshot, app_snapshot != nullptr); isolate = Dart_CreateIsolateGroup( DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, isolate_snapshot_data, isolate_snapshot_instructions, flags, @@ -228,8 +229,8 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, bin::dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size); ASSERT(kernel_service_buffer != nullptr); - isolate_group_data = - new bin::IsolateGroupData(script_uri, packages_config, nullptr, false); + isolate_group_data = new bin::IsolateGroupData( + script_uri, package_root, packages_config, nullptr, false); isolate_group_data->SetKernelBufferUnowned( const_cast(kernel_service_buffer), kernel_service_buffer_size); diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index c8fd5f81283..b01cedcf5f4 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -571,7 +571,10 @@ DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags); * eventually run. This is provided for advisory purposes only to * improve debugging messages. The main function is not invoked by * this function. - * \param package_root Ignored. + * \param package_root The package root path for this isolate to resolve + * package imports against. Only one of package_root and package_map + * parameters is non-NULL. If neither parameter is passed the package + * resolution of the parent isolate should be used. * \param package_map The package map for this isolate to resolve package * imports against. The array contains alternating keys and values, * terminated by a NULL key. Only one of package_root and package_map diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc index 059299d51e0..4ef798d5e43 100644 --- a/runtime/lib/isolate.cc +++ b/runtime/lib/isolate.cc @@ -390,7 +390,7 @@ static const char* String2UTF8(const String& str) { return result; } -DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { +DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) { GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(String, script_uri, arguments->NativeArgAt(1)); GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(2)); @@ -399,8 +399,9 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) { GET_NATIVE_ARGUMENT(Bool, fatalErrors, arguments->NativeArgAt(5)); GET_NATIVE_ARGUMENT(SendPort, onExit, arguments->NativeArgAt(6)); GET_NATIVE_ARGUMENT(SendPort, onError, arguments->NativeArgAt(7)); - GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(8)); - GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(9)); + GET_NATIVE_ARGUMENT(String, packageRoot, arguments->NativeArgAt(8)); + GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(9)); + GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(10)); if (closure.IsClosure()) { Function& func = Function::Handle(); @@ -481,19 +482,26 @@ static const char* CanonicalizeUri(Thread* thread, return result; } -DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) { +DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 13) { GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(1)); + GET_NON_NULL_NATIVE_ARGUMENT(Instance, args, arguments->NativeArgAt(2)); GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(3)); + GET_NON_NULL_NATIVE_ARGUMENT(Bool, paused, arguments->NativeArgAt(4)); GET_NATIVE_ARGUMENT(SendPort, onExit, arguments->NativeArgAt(5)); GET_NATIVE_ARGUMENT(SendPort, onError, arguments->NativeArgAt(6)); + GET_NATIVE_ARGUMENT(Bool, fatalErrors, arguments->NativeArgAt(7)); GET_NATIVE_ARGUMENT(Bool, checked, arguments->NativeArgAt(8)); + GET_NATIVE_ARGUMENT(Array, environment, arguments->NativeArgAt(9)); - GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(10)); - GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(11)); + + GET_NATIVE_ARGUMENT(String, packageRoot, arguments->NativeArgAt(10)); + GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(11)); + + GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(12)); if (Dart::vm_snapshot_kind() == Snapshot::kFullAOT) { const Array& args = Array::Handle(Array::New(1)); diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 8340655e060..65e0dae8864 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -317,8 +317,8 @@ namespace dart { V(Int32x4_setFlagZ, 2) \ V(Int32x4_setFlagW, 2) \ V(Int32x4_select, 3) \ - V(Isolate_spawnFunction, 10) \ - V(Isolate_spawnUri, 12) \ + V(Isolate_spawnFunction, 11) \ + V(Isolate_spawnUri, 13) \ V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) \ V(Isolate_getCurrentRootUriStr, 0) \ V(Isolate_sendOOB, 2) \ diff --git a/sdk/lib/_internal/vm/bin/builtin.dart b/sdk/lib/_internal/vm/bin/builtin.dart index 12fcc14ae9f..b79755ef7ec 100644 --- a/sdk/lib/_internal/vm/bin/builtin.dart +++ b/sdk/lib/_internal/vm/bin/builtin.dart @@ -11,7 +11,6 @@ import 'dart:async'; import 'dart:collection' hide LinkedList, LinkedListEntry; import 'dart:_internal' hide Symbol; import 'dart:io'; -import 'dart:convert'; import 'dart:isolate'; import 'dart:typed_data'; @@ -131,12 +130,11 @@ Uri _resolvePackageUri(Uri uri) { _log('Resolving package with uri path: ${uri.path}'); } var resolvedUri; - final error = _packageError; - if (error != null) { + if (_packageError != null) { if (_traceLoading) { - _log("Resolving package with pending resolution error: $error"); + _log("Resolving package with pending resolution error: $_packageError"); } - throw error; + throw _packageError; } else { if (packageNameEnd < 0) { // Package URIs must have a path after the package name, even if it's @@ -432,67 +430,9 @@ _parsePackagesFile(bool traceLoading, Uri packagesFile, List data) { return result; } -_loadPackageConfigFile(bool traceLoading, Uri packageConfig) { - try { - final Uint8List data = File.fromUri(packageConfig).readAsBytesSync(); - if (traceLoading) { - _log("Loaded package config file from $packageConfig."); - } - return _parsePackageConfig(traceLoading, packageConfig, data); - } catch (e, s) { - if (traceLoading) { - _log("Error loading packages: $e\n$s"); - } - return "Uncaught error ($e) loading packages file."; - } -} - -// The .dart_tool/package_config.json format is described in -// -// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md -// -// The returned list has the format: -// -// [0] Location of package_config.json file. -// [1] null -// [n*2] Name of n-th package -// [n*2 + 1] Location of n-th package's sources (as a String) -// -List _parsePackageConfig( - bool traceLoading, Uri packageConfig, Uint8List bytes) { - final Map packageJson = json.decode(utf8.decode(bytes)); - final version = packageJson['configVersion']; - if (version != 2) { - throw 'The package configuration file has an unsupported version.'; - } - // The first entry contains the location of the identified - // .dart_tool/package_config.json file instead of a mapping. - final result = [packageConfig.toString(), null]; - final List packages = packageJson['packages'] ?? []; - for (final Map package in packages) { - final String name = package['name']; - final String rootUri = package['rootUri']; - final String packageUri = package['packageUri']; - final Uri resolvedRootUri = packageConfig.resolve(rootUri); - final Uri resolvedPackageUri = packageUri != null - ? resolvedRootUri.resolve(packageUri) - : resolvedRootUri; - if (packageUri != null && - !'$resolvedPackageUri'.contains('$resolvedRootUri')) { - throw 'The resolved "packageUri" is not a subdirectory of the "rootUri".'; - } - result.add(name); - result.add(resolvedPackageUri.toString()); - if (traceLoading) { - _log('Resolved package $name to be at $resolvedPackageUri'); - } - } - return result; -} - _loadPackagesFile(bool traceLoading, Uri packagesFile) { try { - final Uint8List data = File.fromUri(packagesFile).readAsBytesSync(); + var data = new File.fromUri(packagesFile).readAsBytesSync(); if (traceLoading) { _log("Loaded packages file from $packagesFile:\n" "${new String.fromCharCodes(data)}"); @@ -506,49 +446,39 @@ _loadPackagesFile(bool traceLoading, Uri packagesFile) { } } -_findPackagesConfiguration(bool traceLoading, Uri base) { +_findPackagesFile(bool traceLoading, Uri base) { try { - // Walk up the directory hierarchy to check for the existence of either one - // of - // - .dart_tool/package_config.json - // - .packages - var currentDir = new File.fromUri(base).parent; - while (true) { - final dirUri = currentDir.uri; - - // We prefer using `.dart_tool/package_config.json` over `.packages`. - final packageConfig = dirUri.resolve(".dart_tool/package_config.json"); - if (traceLoading) { - _log("Checking for $packageConfig file."); - } - bool exists = File.fromUri(packageConfig).existsSync(); - if (traceLoading) { - _log("$packageConfig exists: $exists"); - } - if (exists) { - return _loadPackageConfigFile(traceLoading, packageConfig); - } - - final packagesFile = dirUri.resolve(".packages"); + // Walk up the directory hierarchy to check for the existence of + // .packages files in parent directories and for the existence of a + // packages/ directory on the first iteration. + var dir = new File.fromUri(base).parent; + var prev = null; + // Keep searching until we reach the root. + while ((prev == null) || (prev.path != dir.path)) { + // Check for the existence of a .packages file and if it exists try to + // load and parse it. + var dirUri = dir.uri; + var packagesFile = dirUri.resolve(".packages"); if (traceLoading) { _log("Checking for $packagesFile file."); } - exists = File.fromUri(packagesFile).existsSync(); + var exists = new File.fromUri(packagesFile).existsSync(); if (traceLoading) { _log("$packagesFile exists: $exists"); } if (exists) { return _loadPackagesFile(traceLoading, packagesFile); } - final parentDir = currentDir.parent; - if (currentDir == parentDir) break; - currentDir = parentDir; + // Move up one level. + prev = dir; + dir = dir.parent; } + // No .packages file was found. if (traceLoading) { - _log("Could not resolve a package configuration from $base"); + _log("Could not resolve a package location from $base"); } - return "Could not resolve a package configuration for base at $base"; + return "Could not resolve a package location for base at $base"; } catch (e, s) { if (traceLoading) { _log("Error loading packages: $e\n$s"); @@ -579,7 +509,7 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) { try { if (tag == -1) { if (resource.scheme == '' || resource.scheme == 'file') { - return _findPackagesConfiguration(traceLoading, resource); + return _findPackagesFile(traceLoading, resource); } else { return "Unsupported scheme used to locate .packages file:'$resource'."; } @@ -650,9 +580,6 @@ void _setWorkingDirectory(String cwd) { } // 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. @pragma("vm:entry-point") String _setPackagesMap(String packagesParam) { if (!_setupCompleted) { diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart index 76a8a88bb0b..6accfc3d598 100644 --- a/sdk/lib/_internal/vm/lib/internal_patch.dart +++ b/sdk/lib/_internal/vm/lib/internal_patch.dart @@ -48,6 +48,7 @@ class VMLibraryHooks { // Implementation of package root/map provision. static var packageRootString; static var packageConfigString; + static var packageRootUriFuture; static var packageConfigUriFuture; static var resolvePackageUriFuture; diff --git a/sdk/lib/_internal/vm/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart index e357b8a0874..e17c1de0323 100644 --- a/sdk/lib/_internal/vm/lib/isolate_patch.dart +++ b/sdk/lib/_internal/vm/lib/isolate_patch.dart @@ -267,21 +267,21 @@ void _startIsolate( // The control port (aka the main isolate port) does not handle any messages. if (controlPort != null) { controlPort.handler = (_) {}; // Nobody home on the control port. + } - if (parentPort != null) { - // Build a message to our parent isolate providing access to the - // current isolate's control port and capabilities. - // - // TODO(floitsch): Send an error message if we can't find the entry point. - final readyMessage = List(2); - readyMessage[0] = controlPort.sendPort; - readyMessage[1] = capabilities; + if (parentPort != null) { + // Build a message to our parent isolate providing access to the + // current isolate's control port and capabilities. + // + // TODO(floitsch): Send an error message if we can't find the entry point. + var readyMessage = new List(2); + readyMessage[0] = controlPort.sendPort; + readyMessage[1] = capabilities; - // Out of an excess of paranoia we clear the capabilities from the - // stack. Not really necessary. - capabilities = null; - parentPort.send(readyMessage); - } + // Out of an excess of paranoia we clear the capabilities from the + // stack. Not really necessary. + capabilities = null; + parentPort.send(readyMessage); } assert(capabilities == null); @@ -343,6 +343,7 @@ class Isolate { } static bool _packageSupported() => + (VMLibraryHooks.packageRootUriFuture != null) && (VMLibraryHooks.packageConfigUriFuture != null) && (VMLibraryHooks.resolvePackageUriFuture != null); @@ -354,33 +355,46 @@ class Isolate { SendPort onError, String debugName}) async { // `paused` isn't handled yet. - // Check for the type of `entryPoint` on the spawning isolate to make - // error-handling easier. - if (entryPoint is! _UnaryFunction) { - throw new ArgumentError(entryPoint); - } - // The VM will invoke [_startIsolate] with entryPoint as argument. - - // We do not inherit the package config settings from the parent isolate, - // instead we use the values that were set on the command line. - var packageConfig = VMLibraryHooks.packageConfigString; - var script = VMLibraryHooks.platformScript; - if (script == null) { - // We do not have enough information to support spawning the new - // isolate. - throw new UnsupportedError("Isolate.spawn"); - } - if (script.isScheme("package")) { - script = await Isolate.resolvePackageUri(script); - } - - final RawReceivePort readyPort = new RawReceivePort(); + RawReceivePort readyPort; try { - _spawnFunction(readyPort.sendPort, script.toString(), entryPoint, message, - paused, errorsAreFatal, onExit, onError, packageConfig, debugName); + // Check for the type of `entryPoint` on the spawning isolate to make + // error-handling easier. + if (entryPoint is! _UnaryFunction) { + throw new ArgumentError(entryPoint); + } + // The VM will invoke [_startIsolate] with entryPoint as argument. + readyPort = new RawReceivePort(); + + // We do not inherit the package config settings from the parent isolate, + // instead we use the values that were set on the command line. + var packageConfig = VMLibraryHooks.packageConfigString; + var script = VMLibraryHooks.platformScript; + if (script == null) { + // We do not have enough information to support spawning the new + // isolate. + throw new UnsupportedError("Isolate.spawn"); + } + if (script.scheme == "package") { + script = await Isolate.resolvePackageUri(script); + } + + _spawnFunction( + readyPort.sendPort, + script.toString(), + entryPoint, + message, + paused, + errorsAreFatal, + onExit, + onError, + null, + packageConfig, + debugName); return await _spawnCommon(readyPort); } catch (e, st) { - readyPort.close(); + if (readyPort != null) { + readyPort.close(); + } return await new Future.error(e, st); } } @@ -397,6 +411,7 @@ class Isolate { Uri packageConfig, bool automaticPackageResolution: false, String debugName}) async { + RawReceivePort readyPort; if (environment != null) { throw new UnimplementedError("environment"); } @@ -419,30 +434,38 @@ class Isolate { "packageRoot and a packageConfig."); } } - // Resolve the uri against the current isolate's root Uri first. - final Uri spawnedUri = _rootUri.resolveUri(uri); - - // Inherit this isolate's package resolution setup if not overridden. - if (!automaticPackageResolution && packageConfig == null) { - if (Isolate._packageSupported()) { - packageConfig = await Isolate.packageConfig; - } - } - - // Ensure to resolve package: URIs being handed in as parameters. - if (packageConfig != null) { - // Avoid calling resolvePackageUri if not strictly necessary in case - // the API is not supported. - if (packageConfig.isScheme("package")) { - packageConfig = await Isolate.resolvePackageUri(packageConfig); - } - } - - // The VM will invoke [_startIsolate] and not `main`. - final packageConfigString = packageConfig?.toString(); - - final RawReceivePort readyPort = new RawReceivePort(); try { + // Resolve the uri against the current isolate's root Uri first. + var spawnedUri = _rootUri.resolveUri(uri); + + // Inherit this isolate's package resolution setup if not overridden. + if (!automaticPackageResolution && + (packageRoot == null) && + (packageConfig == null)) { + if (Isolate._packageSupported()) { + packageRoot = await Isolate.packageRoot; + packageConfig = await Isolate.packageConfig; + } + } + + // Ensure to resolve package: URIs being handed in as parameters. + if (packageRoot != null) { + // `packages/` directory is no longer supported. Force it null. + // TODO(mfairhurst) Should this throw an exception? + packageRoot = null; + } else if (packageConfig != null) { + // Avoid calling resolvePackageUri if not strictly necessary in case + // the API is not supported. + if (packageConfig.scheme == "package") { + packageConfig = await Isolate.resolvePackageUri(packageConfig); + } + } + + // The VM will invoke [_startIsolate] and not `main`. + readyPort = new RawReceivePort(); + var packageRootString = packageRoot?.toString(); + var packageConfigString = packageConfig?.toString(); + _spawnUri( readyPort.sendPort, spawnedUri.toString(), @@ -455,17 +478,20 @@ class Isolate { checked, null, /* environment */ + packageRootString, packageConfigString, debugName); return await _spawnCommon(readyPort); } catch (e) { - readyPort.close(); + if (readyPort != null) { + readyPort.close(); + } rethrow; } } static Future _spawnCommon(RawReceivePort readyPort) { - final completer = new Completer.sync(); + Completer completer = new Completer.sync(); readyPort.handler = (readyMessage) { readyPort.close(); if (readyMessage is List && readyMessage.length == 2) { @@ -510,6 +536,7 @@ class Isolate { bool errorsAreFatal, SendPort onExit, SendPort onError, + String packageRoot, String packageConfig, String debugName) native "Isolate_spawnFunction"; @@ -524,6 +551,7 @@ class Isolate { bool errorsAreFatal, bool checked, List environment, + String packageRoot, String packageConfig, String debugName) native "Isolate_spawnUri"; diff --git a/sdk_nnbd/lib/_internal/vm/bin/builtin.dart b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart index 11d589c7dbe..1befe5ac475 100644 --- a/sdk_nnbd/lib/_internal/vm/bin/builtin.dart +++ b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart @@ -9,7 +9,6 @@ import 'dart:async'; import 'dart:collection' hide LinkedList, LinkedListEntry; import 'dart:_internal' hide Symbol; import 'dart:io'; -import 'dart:convert'; import 'dart:isolate'; import 'dart:typed_data'; @@ -431,67 +430,9 @@ _parsePackagesFile(bool traceLoading, Uri packagesFile, List data) { return result; } -_loadPackageConfigFile(bool traceLoading, Uri packageConfig) { - try { - final Uint8List data = File.fromUri(packageConfig).readAsBytesSync(); - if (traceLoading) { - _log("Loaded package config file from $packageConfig."); - } - return _parsePackageConfig(traceLoading, packageConfig, data); - } catch (e, s) { - if (traceLoading) { - _log("Error loading packages: $e\n$s"); - } - return "Uncaught error ($e) loading packages file."; - } -} - -// The .dart_tool/package_config.json format is described in -// -// https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md -// -// The returned list has the format: -// -// [0] Location of package_config.json file. -// [1] null -// [n*2] Name of n-th package -// [n*2 + 1] Location of n-th package's sources (as a String) -// -List _parsePackageConfig( - bool traceLoading, Uri packageConfig, Uint8List bytes) { - final Map packageJson = json.decode(utf8.decode(bytes)); - final version = packageJson['configVersion']; - if (version != 2) { - throw 'The package configuration file has an unsupported version.'; - } - // The first entry contains the location of the identified - // .dart_tool/package_config.json file instead of a mapping. - final result = [packageConfig.toString(), null]; - final List packages = packageJson['packages'] ?? []; - for (final Map package in packages) { - final String name = package['name']; - final String rootUri = package['rootUri']; - final String? packageUri = package['packageUri']; - final Uri resolvedRootUri = packageConfig.resolve(rootUri); - final Uri resolvedPackageUri = packageUri != null - ? resolvedRootUri.resolve(packageUri) - : resolvedRootUri; - if (packageUri != null && - !'$resolvedPackageUri'.contains('$resolvedRootUri')) { - throw 'The resolved "packageUri" is not a subdirectory of the "rootUri".'; - } - result.add(name); - result.add(resolvedPackageUri.toString()); - if (traceLoading) { - _log('Resolved package $name to be at $resolvedPackageUri'); - } - } - return result; -} - _loadPackagesFile(bool traceLoading, Uri packagesFile) { try { - final Uint8List data = File.fromUri(packagesFile).readAsBytesSync(); + var data = new File.fromUri(packagesFile).readAsBytesSync(); if (traceLoading) { _log("Loaded packages file from $packagesFile:\n" "${new String.fromCharCodes(data)}"); @@ -505,49 +446,39 @@ _loadPackagesFile(bool traceLoading, Uri packagesFile) { } } -_findPackagesConfiguration(bool traceLoading, Uri base) { +_findPackagesFile(bool traceLoading, Uri base) { try { - // Walk up the directory hierarchy to check for the existence of either one - // of - // - .dart_tool/package_config.json - // - .packages - var currentDir = new File.fromUri(base).parent; - while (true) { - final dirUri = currentDir.uri; - - // We prefer using `.dart_tool/package_config.json` over `.packages`. - final packageConfig = dirUri.resolve(".dart_tool/package_config.json"); - if (traceLoading) { - _log("Checking for $packageConfig file."); - } - bool exists = File.fromUri(packageConfig).existsSync(); - if (traceLoading) { - _log("$packageConfig exists: $exists"); - } - if (exists) { - return _loadPackageConfigFile(traceLoading, packageConfig); - } - - final packagesFile = dirUri.resolve(".packages"); + // Walk up the directory hierarchy to check for the existence of + // .packages files in parent directories and for the existence of a + // packages/ directory on the first iteration. + var dir = new File.fromUri(base).parent; + var prev = null; + // Keep searching until we reach the root. + while ((prev == null) || (prev.path != dir.path)) { + // Check for the existence of a .packages file and if it exists try to + // load and parse it. + var dirUri = dir.uri; + var packagesFile = dirUri.resolve(".packages"); if (traceLoading) { _log("Checking for $packagesFile file."); } - exists = File.fromUri(packagesFile).existsSync(); + var exists = new File.fromUri(packagesFile).existsSync(); if (traceLoading) { _log("$packagesFile exists: $exists"); } if (exists) { return _loadPackagesFile(traceLoading, packagesFile); } - final parentDir = currentDir.parent; - if (currentDir == parentDir) break; - currentDir = parentDir; + // Move up one level. + prev = dir; + dir = dir.parent; } + // No .packages file was found. if (traceLoading) { - _log("Could not resolve a package configuration from $base"); + _log("Could not resolve a package location from $base"); } - return "Could not resolve a package configuration for base at $base"; + return "Could not resolve a package location for base at $base"; } catch (e, s) { if (traceLoading) { _log("Error loading packages: $e\n$s"); @@ -578,7 +509,7 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) { try { if (tag == -1) { if (resource.scheme == '' || resource.scheme == 'file') { - return _findPackagesConfiguration(traceLoading, resource); + return _findPackagesFile(traceLoading, resource); } else { return "Unsupported scheme used to locate .packages file:'$resource'."; } @@ -649,9 +580,6 @@ void _setWorkingDirectory(String cwd) { } // 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. @pragma("vm:entry-point") String _setPackagesMap(String packagesParam) { if (!_setupCompleted) { diff --git a/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart index 2faf79976cb..b484a2c1dfc 100644 --- a/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart +++ b/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart @@ -52,6 +52,7 @@ class VMLibraryHooks { // Implementation of package root/map provision. static var packageRootString; static var packageConfigString; + static var packageRootUriFuture; static var packageConfigUriFuture; static var resolvePackageUriFuture; diff --git a/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart index 7658010500f..77e38440737 100644 --- a/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart +++ b/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart @@ -272,7 +272,7 @@ void _startIsolate( // current isolate's control port and capabilities. // // TODO(floitsch): Send an error message if we can't find the entry point. - final readyMessage = List.filled(2, null); + var readyMessage = new List.filled(2, null); readyMessage[0] = controlPort.sendPort; readyMessage[1] = capabilities; @@ -342,6 +342,7 @@ class Isolate { } static bool _packageSupported() => + (VMLibraryHooks.packageRootUriFuture != null) && (VMLibraryHooks.packageConfigUriFuture != null) && (VMLibraryHooks.resolvePackageUriFuture != null); @@ -375,8 +376,18 @@ class Isolate { final RawReceivePort readyPort = new RawReceivePort(); try { - _spawnFunction(readyPort.sendPort, script.toString(), entryPoint, message, - paused, errorsAreFatal, onExit, onError, packageConfig, debugName); + _spawnFunction( + readyPort.sendPort, + script.toString(), + entryPoint, + message, + paused, + errorsAreFatal, + onExit, + onError, + null, + packageConfig, + debugName); return await _spawnCommon(readyPort); } catch (e, st) { readyPort.close(); @@ -419,17 +430,24 @@ class Isolate { } } // Resolve the uri against the current isolate's root Uri first. - final Uri spawnedUri = _rootUri!.resolveUri(uri); + var spawnedUri = _rootUri!.resolveUri(uri); // Inherit this isolate's package resolution setup if not overridden. - if (!automaticPackageResolution && packageConfig == null) { + if (!automaticPackageResolution && + (packageRoot == null) && + (packageConfig == null)) { if (Isolate._packageSupported()) { + packageRoot = await Isolate.packageRoot; packageConfig = await Isolate.packageConfig; } } // Ensure to resolve package: URIs being handed in as parameters. - if (packageConfig != null) { + if (packageRoot != null) { + // `packages/` directory is no longer supported. Force it null. + // TODO(mfairhurst) Should this throw an exception? + packageRoot = null; + } else if (packageConfig != null) { // Avoid calling resolvePackageUri if not strictly necessary in case // the API is not supported. if (packageConfig.isScheme("package")) { @@ -438,7 +456,8 @@ class Isolate { } // The VM will invoke [_startIsolate] and not `main`. - final packageConfigString = packageConfig?.toString(); + var packageRootString = packageRoot?.toString(); + var packageConfigString = packageConfig?.toString(); final RawReceivePort readyPort = new RawReceivePort(); try { @@ -454,6 +473,7 @@ class Isolate { checked, null, /* environment */ + packageRootString, packageConfigString, debugName); return await _spawnCommon(readyPort); @@ -509,6 +529,7 @@ class Isolate { bool errorsAreFatal, SendPort? onExit, SendPort? onError, + String? packageRoot, String? packageConfig, String? debugName) native "Isolate_spawnFunction"; @@ -523,6 +544,7 @@ class Isolate { bool errorsAreFatal, bool? checked, List? environment, + String? packageRoot, String? packageConfig, String? debugName) native "Isolate_spawnUri"; diff --git a/tests/lib/isolate/spawn_uri__package_uri__test.dart b/tests/lib/isolate/spawn_uri__package_uri__test.dart deleted file mode 100644 index 313a55b95e0..00000000000 --- a/tests/lib/isolate/spawn_uri__package_uri__test.dart +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:expect/expect.dart'; -import 'package:path/path.dart' as path; - -final executable = Platform.executable; - -main() async { - // Run the Dart VM with or without: - // --packages= - for (final runWithPackagesArg in const [true, false]) { - // Run the isolate with or without - // Isolate.spawnUri(..., packageConfig: ) - print('TEST runWithPackagesArg = $runWithPackagesArg '); - for (final spawnWithPackageConfig in const [true, false]) { - print('TEST spawnWithPackageConfig = $spawnWithPackageConfig '); - await runDotPackagesTest(runWithPackagesArg, spawnWithPackageConfig); - for (final optionalPackageUri in const [true, false]) { - print('TEST optionalPackageUri = $optionalPackageUri'); - await runPackageConfigTest( - runWithPackagesArg, spawnWithPackageConfig, optionalPackageUri); - } - } - } -} - -Future runPackageConfigTest( - bool withPackagesArg, bool spawnWithArg, bool optionalPackageUri) async { - await withApplicationDirAndDotDartToolPackageConfig( - (String tempDir, String packageJson, String mainFile) async { - final args = [if (withPackagesArg) '--packages=$packageJson', mainFile]; - await run(executable, args); - }, spawnWithArg, optionalPackageUri); -} - -Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async { - await withApplicationDirAndDotPackages( - (String tempDir, String dotPackagesFile, String mainFile) async { - final args = [ - if (withPackagesArg) '--packages=$dotPackagesFile', - mainFile, - ]; - await run(executable, args); - }, spawnWithArg); -} - -Future withApplicationDirAndDotPackages( - Future fn(String tempDir, String packagesDir, String mainFile), - bool spawnWithArg) async { - await withTempDir((String tempDir) async { - // Setup ".packages" - final dotPackagesFile = - path.join(tempDir, spawnWithArg ? 'baz.packages' : '.packages'); - await File(dotPackagesFile).writeAsString(buildDotPackages('foo')); - - final mainFile = path.join(tempDir, 'main.dart'); - final childIsolateFile = path.join(tempDir, 'child_isolate.dart'); - final importUri = 'package:foo/child_isolate.dart'; - await File(childIsolateFile).writeAsString(buildChildIsolate()); - await File(mainFile).writeAsString( - buildMainIsolate(importUri, spawnWithArg ? dotPackagesFile : null)); - - await fn(tempDir, dotPackagesFile, mainFile); - }); -} - -Future withApplicationDirAndDotDartToolPackageConfig( - Future fn(String tempDir, String packageJson, String mainFile), - bool spawnWithArg, - bool optionalPackageUri) async { - await withTempDir((String tempDir) async { - // Setup ".dart_tool/package_config.json" - final dotDartToolDir = path.join(tempDir, '.dart_tool'); - await Directory(dotDartToolDir).create(); - final packageConfigJsonFile = path.join( - dotDartToolDir, spawnWithArg ? 'baz.packages' : 'package_config.json'); - await File(packageConfigJsonFile) - .writeAsString(buildPackageConfig('foo', optionalPackageUri)); - - // Setup actual application - final mainFile = path.join(tempDir, 'main.dart'); - final childIsolateFile = path.join(tempDir, 'child_isolate.dart'); - final importUri = 'package:foo/child_isolate.dart'; - await File(childIsolateFile).writeAsString(buildChildIsolate()); - await File(mainFile).writeAsString(buildMainIsolate( - importUri, spawnWithArg ? packageConfigJsonFile : null)); - - await fn(tempDir, packageConfigJsonFile, mainFile); - }); -} - -Future withTempDir(Future fn(String dir)) async { - final dir = await Directory.systemTemp.createTemp('spawn_uri'); - try { - await fn(dir.absolute.path); - } finally { - await dir.delete(recursive: true); - } -} - -Future run(String executable, List args, - {String? cwd}) async { - print('Running $executable ${args.join(' ')}'); - final String workingDirectory = cwd ?? Directory.current.absolute.path; - final result = await Process.run(executable, ['--trace-loading', ...args], - workingDirectory: workingDirectory); - print('exitCode:\n${result.exitCode}'); - print('stdout:\n${result.stdout}'); - print('stdout:\n${result.stderr}'); - Expect.equals(0, result.exitCode); - return result; -} - -String buildDotPackages(String packageName) => '$packageName:.'; - -String buildPackageConfig(String packageName, bool optionalPackageUri) => ''' -{ - "configVersion": 2, - "packages": [ - { - "name": "$packageName", - "rootUri": "../" - ${optionalPackageUri ? ', "packageUri": "./"' : ''} - } - ] -} -'''; - -String buildChildIsolate() => ''' - import 'dart:isolate'; - - main(List args, SendPort message) { - message.send('child isolate is done'); - } -'''; - -String buildMainIsolate(String spawnUri, String? packageConfigUri) => ''' - import 'dart:isolate'; - import 'dart:io' as io; - - main(List args) async { - io.exitCode = 1; - - final rp = ReceivePort(); - final uri = Uri.parse('$spawnUri'); - final isolateArgs = ['a']; - await Isolate.spawnUri( - uri, - isolateArgs, - rp.sendPort, - packageConfig: ${packageConfigUri != null ? 'Uri.file(r"$packageConfigUri")' : 'null'}); - final childIsolateMessage = await rp.first; - if (childIsolateMessage != 'child isolate is done') { - throw 'Did not receive correct message from child isolate.'; - } - - // Test was successful. - io.exitCode = 0; - } -'''; diff --git a/tests/lib_2/isolate/spawn_uri__package_uri__test.dart b/tests/lib_2/isolate/spawn_uri__package_uri__test.dart deleted file mode 100644 index f34eb4646a8..00000000000 --- a/tests/lib_2/isolate/spawn_uri__package_uri__test.dart +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:expect/expect.dart'; -import 'package:path/path.dart' as path; - -final executable = Platform.executable; - -main() async { - // Run the Dart VM with or without: - // --packages= - for (final runWithPackagesArg in const [true, false]) { - // Run the isolate with or without - // Isolate.spawnUri(..., packageConfig: ) - print('TEST runWithPackagesArg = $runWithPackagesArg '); - for (final spawnWithPackageConfig in const [true, false]) { - print('TEST spawnWithPackageConfig = $spawnWithPackageConfig '); - await runDotPackagesTest(runWithPackagesArg, spawnWithPackageConfig); - for (final optionalPackageUri in const [true, false]) { - print('TEST optionalPackageUri = $optionalPackageUri'); - await runPackageConfigTest( - runWithPackagesArg, spawnWithPackageConfig, optionalPackageUri); - } - } - } -} - -Future runPackageConfigTest( - bool withPackagesArg, bool spawnWithArg, bool optionalPackageUri) async { - await withApplicationDirAndDotDartToolPackageConfig( - (String tempDir, String packageJson, String mainFile) async { - final args = [if (withPackagesArg) '--packages=$packageJson', mainFile]; - await run(executable, args); - }, spawnWithArg, optionalPackageUri); -} - -Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async { - await withApplicationDirAndDotPackages( - (String tempDir, String dotPackagesFile, String mainFile) async { - final args = [ - if (withPackagesArg) '--packages=$dotPackagesFile', - mainFile, - ]; - await run(executable, args); - }, spawnWithArg); -} - -Future withApplicationDirAndDotPackages( - Future fn(String tempDir, String packagesDir, String mainFile), - bool spawnWithArg) async { - await withTempDir((String tempDir) async { - // Setup ".packages" - final dotPackagesFile = - path.join(tempDir, spawnWithArg ? 'baz.packages' : '.packages'); - await File(dotPackagesFile).writeAsString(buildDotPackages('foo')); - - final mainFile = path.join(tempDir, 'main.dart'); - final childIsolateFile = path.join(tempDir, 'child_isolate.dart'); - final importUri = 'package:foo/child_isolate.dart'; - await File(childIsolateFile).writeAsString(buildChildIsolate()); - await File(mainFile).writeAsString( - buildMainIsolate(importUri, spawnWithArg ? dotPackagesFile : null)); - - await fn(tempDir, dotPackagesFile, mainFile); - }); -} - -Future withApplicationDirAndDotDartToolPackageConfig( - Future fn(String tempDir, String packageJson, String mainFile), - bool spawnWithArg, - bool optionalPackageUri) async { - await withTempDir((String tempDir) async { - // Setup ".dart_tool/package_config.json" - final dotDartToolDir = path.join(tempDir, '.dart_tool'); - await Directory(dotDartToolDir).create(); - final packageConfigJsonFile = path.join( - dotDartToolDir, spawnWithArg ? 'baz.packages' : 'package_config.json'); - await File(packageConfigJsonFile) - .writeAsString(buildPackageConfig('foo', optionalPackageUri)); - - // Setup actual application - final mainFile = path.join(tempDir, 'main.dart'); - final childIsolateFile = path.join(tempDir, 'child_isolate.dart'); - final importUri = 'package:foo/child_isolate.dart'; - await File(childIsolateFile).writeAsString(buildChildIsolate()); - await File(mainFile).writeAsString(buildMainIsolate( - importUri, spawnWithArg ? packageConfigJsonFile : null)); - - await fn(tempDir, packageConfigJsonFile, mainFile); - }); -} - -Future withTempDir(Future fn(String dir)) async { - final dir = await Directory.systemTemp.createTemp('spawn_uri'); - try { - await fn(dir.absolute.path); - } finally { - await dir.delete(recursive: true); - } -} - -Future run(String executable, List args, - {String cwd}) async { - print('Running $executable ${args.join(' ')}'); - final String workingDirectory = cwd ?? Directory.current.absolute.path; - final result = await Process.run(executable, ['--trace-loading', ...args], - workingDirectory: workingDirectory); - print('exitCode:\n${result.exitCode}'); - print('stdout:\n${result.stdout}'); - print('stdout:\n${result.stderr}'); - Expect.equals(0, result.exitCode); - return result; -} - -String buildDotPackages(String packageName) => '$packageName:.'; - -String buildPackageConfig(String packageName, bool optionalPackageUri) => ''' -{ - "configVersion": 2, - "packages": [ - { - "name": "$packageName", - "rootUri": "../" - ${optionalPackageUri ? ', "packageUri": "./"' : ''} - } - ] -} -'''; - -String buildChildIsolate() => ''' - import 'dart:isolate'; - - main(List args, SendPort message) { - message.send('child isolate is done'); - } -'''; - -String buildMainIsolate(String spawnUri, String packageConfigUri) => ''' - import 'dart:isolate'; - import 'dart:io' as io; - - main(List args) async { - io.exitCode = 1; - - final rp = ReceivePort(); - final uri = Uri.parse('$spawnUri'); - final isolateArgs = ['a']; - await Isolate.spawnUri( - uri, - isolateArgs, - rp.sendPort, - packageConfig: ${packageConfigUri != null ? 'Uri.file(r"$packageConfigUri")' : 'null'}); - final childIsolateMessage = await rp.first; - if (childIsolateMessage != 'child isolate is done') { - throw 'Did not receive correct message from child isolate.'; - } - - // Test was successful. - io.exitCode = 0; - } -'''; diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status index 855ab434c61..432516aa1d9 100644 --- a/tests/lib_2/lib_2.status +++ b/tests/lib_2/lib_2.status @@ -24,9 +24,6 @@ html/indexeddb_1_test/functional: Skip # Times out. Issue 21433 html/indexeddb_3_test: Skip # Times out 1 out of 10. html/worker_api_test: Skip # Issue 13221 -[ $runtime != vm ] -isolate/spawn_uri__package_uri__test: SkipByDesign # This test uses Isolate.spawnUri and only works in JIT mode. - [ $system == windows ] html/xhr_test/xhr: Skip # Times out. Issue 21527 diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status index 77c441a046e..78b99864325 100644 --- a/tests/lib_2/lib_2_vm.status +++ b/tests/lib_2/lib_2_vm.status @@ -137,7 +137,6 @@ isolate/simple_message_test: Skip # https://dartbug.com/36097: Ongoing concurren isolate/spawn_function_custom_class_test: Skip # https://dartbug.com/36097: Ongoing concurrency work. isolate/spawn_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work. isolate/spawn_generic_test: Skip # https://dartbug.com/36097: Ongoing concurrency work. -isolate/spawn_uri__package_uri__test: Skip # https://dartbug.com/36097: Ongoing concurrency work. isolate/spawn_uri_exported_main_test: Skip # https://dartbug.com/36097: Ongoing concurrency work. isolate/spawn_uri_missing_from_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work. isolate/spawn_uri_missing_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.