mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:47:08 +00:00
Reland "[vm] Make VM support .dart_tool/package_config.json"
This CL makes the VM add support for .dart_tool/package_config.json via * the --packages=<file> command line parameter * the `packageConfig: <file>` parameter to `Isolate.spawnUri` It also allows now `package:*` uris being used in `Isolate.spawnUri` The CL also removes the unused `packageRoot` parameter from the Dart to C++ interface as well as in various places in C++. The CL also aligns the implementations between sdk and sdk_nnbd more. Issue https://github.com/dart-lang/sdk/issues/41649 Issue https://github.com/dart-lang/sdk/issues/41245 Issue https://github.com/dart-lang/sdk/issues/41246 Change-Id: I0a7aa3040332abafa19bf80bdbd8a8f8594cc6fe Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145462 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
e580dd8e84
commit
fa6cc57a32
|
@ -670,7 +670,7 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
|
|||
}
|
||||
|
||||
auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
|
||||
new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false));
|
||||
new IsolateGroupData(nullptr, nullptr, nullptr, false));
|
||||
Dart_Isolate isolate;
|
||||
char* error = NULL;
|
||||
|
||||
|
|
|
@ -10,21 +10,16 @@ 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 (package_root != NULL) {
|
||||
ASSERT(packages_file == NULL);
|
||||
package_root = strdup(package_root);
|
||||
} else if (packages_file != NULL) {
|
||||
if (packages_file != NULL) {
|
||||
packages_file_ = strdup(packages_file);
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +27,6 @@ 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_);
|
||||
|
|
|
@ -34,14 +34,12 @@ 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<uint8_t>& kernel_buffer() const {
|
||||
return kernel_buffer_;
|
||||
|
|
|
@ -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 root' for URI resolution.
|
||||
// Set up package configuration for URI resolution.
|
||||
result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
|
||||
if (Dart_IsError(result)) return result;
|
||||
|
||||
|
@ -417,7 +417,6 @@ 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,
|
||||
|
@ -459,9 +458,8 @@ 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, package_root, packages_config, app_snapshot,
|
||||
isolate_run_app_snapshot);
|
||||
isolate_group_data = new IsolateGroupData(
|
||||
uri, 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,
|
||||
|
@ -479,8 +477,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, package_root, packages_config, nullptr, isolate_run_app_snapshot);
|
||||
isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr,
|
||||
isolate_run_app_snapshot);
|
||||
isolate_group_data->SetKernelBufferUnowned(
|
||||
const_cast<uint8_t*>(kernel_service_buffer),
|
||||
kernel_service_buffer_size);
|
||||
|
@ -508,7 +506,6 @@ 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,
|
||||
|
@ -516,8 +513,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, package_root, packages_config, nullptr, false);
|
||||
auto isolate_group_data =
|
||||
new IsolateGroupData(script_uri, packages_config, nullptr, false);
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
// AOT: All isolates start from the app snapshot.
|
||||
|
@ -580,7 +577,6 @@ 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,
|
||||
|
@ -637,9 +633,8 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
|||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
auto isolate_group_data =
|
||||
new IsolateGroupData(script_uri, package_root, packages_config,
|
||||
app_snapshot, isolate_run_app_snapshot);
|
||||
auto isolate_group_data = new IsolateGroupData(
|
||||
script_uri, packages_config, app_snapshot, isolate_run_app_snapshot);
|
||||
if (kernel_buffer != NULL) {
|
||||
if (parent_kernel_buffer) {
|
||||
isolate_group_data->SetKernelBufferAlreadyOwned(
|
||||
|
@ -716,28 +711,22 @@ 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);
|
||||
if ((package_root != NULL) && (package_config != NULL)) {
|
||||
*error = strdup(
|
||||
"Invalid arguments - Cannot simultaneously specify "
|
||||
"package root and package map.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT(package_root == nullptr);
|
||||
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_root, package_config,
|
||||
flags, error, &exit_code);
|
||||
return CreateAndSetupKernelIsolate(script_uri, 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_root, package_config, flags, error, &exit_code);
|
||||
return CreateAndSetupServiceIsolate(script_uri, package_config, flags,
|
||||
error, &exit_code);
|
||||
}
|
||||
bool is_main_isolate = false;
|
||||
return CreateIsolateGroupAndSetupHelper(is_main_isolate, script_uri, main,
|
||||
package_root, package_config, flags,
|
||||
callback_data, error, &exit_code);
|
||||
package_config, flags, callback_data,
|
||||
error, &exit_code);
|
||||
}
|
||||
|
||||
static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) {
|
||||
|
@ -845,10 +834,15 @@ 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::package_root(),
|
||||
Options::packages_file(), &flags, NULL /* callback_data */, &error,
|
||||
&exit_code);
|
||||
is_main_isolate, script_name, "main", Options::packages_file(), &flags,
|
||||
NULL /* callback_data */, &error, &exit_code);
|
||||
|
||||
if (isolate == NULL) {
|
||||
Syslog::PrintErr("%s\n", error);
|
||||
|
|
|
@ -101,7 +101,6 @@ static void PrintUsage() {
|
|||
}
|
||||
|
||||
static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
const char* package_root,
|
||||
const char* packages_config,
|
||||
Dart_IsolateFlags* flags,
|
||||
char** error) {
|
||||
|
@ -117,7 +116,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, package_root, packages_config, /*app_snapshot=*/nullptr,
|
||||
script_uri, packages_config, /*app_snapshot=*/nullptr,
|
||||
/*isolate_run_app_snapshot=*/false);
|
||||
|
||||
const uint8_t* kernel_buffer = nullptr;
|
||||
|
@ -169,9 +168,10 @@ 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, package_root,
|
||||
packages_config, flags, error);
|
||||
return CreateAndSetupServiceIsolate(script_uri, packages_config, flags,
|
||||
error);
|
||||
}
|
||||
const bool is_kernel_isolate =
|
||||
strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0;
|
||||
|
@ -200,9 +200,8 @@ 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, package_root, packages_config,
|
||||
app_snapshot, app_snapshot != nullptr);
|
||||
isolate_group_data = new bin::IsolateGroupData(
|
||||
script_uri, 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,
|
||||
|
@ -229,8 +228,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, package_root, packages_config, nullptr, false);
|
||||
isolate_group_data =
|
||||
new bin::IsolateGroupData(script_uri, packages_config, nullptr, false);
|
||||
isolate_group_data->SetKernelBufferUnowned(
|
||||
const_cast<uint8_t*>(kernel_service_buffer),
|
||||
kernel_service_buffer_size);
|
||||
|
|
|
@ -571,10 +571,7 @@ 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 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_root Ignored.
|
||||
* \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
|
||||
|
|
|
@ -390,7 +390,7 @@ static const char* String2UTF8(const String& str) {
|
|||
return result;
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) {
|
||||
DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) {
|
||||
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,9 +399,8 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) {
|
|||
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, packageRoot, arguments->NativeArgAt(8));
|
||||
GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(9));
|
||||
GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(10));
|
||||
GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(8));
|
||||
GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(9));
|
||||
|
||||
if (closure.IsClosure()) {
|
||||
Function& func = Function::Handle();
|
||||
|
@ -482,26 +481,19 @@ static const char* CanonicalizeUri(Thread* thread,
|
|||
return result;
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 13) {
|
||||
DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) {
|
||||
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, packageRoot, arguments->NativeArgAt(10));
|
||||
GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(11));
|
||||
|
||||
GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(12));
|
||||
GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(10));
|
||||
GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(11));
|
||||
|
||||
if (Dart::vm_snapshot_kind() == Snapshot::kFullAOT) {
|
||||
const Array& args = Array::Handle(Array::New(1));
|
||||
|
|
|
@ -317,8 +317,8 @@ namespace dart {
|
|||
V(Int32x4_setFlagZ, 2) \
|
||||
V(Int32x4_setFlagW, 2) \
|
||||
V(Int32x4_select, 3) \
|
||||
V(Isolate_spawnFunction, 11) \
|
||||
V(Isolate_spawnUri, 13) \
|
||||
V(Isolate_spawnFunction, 10) \
|
||||
V(Isolate_spawnUri, 12) \
|
||||
V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) \
|
||||
V(Isolate_getCurrentRootUriStr, 0) \
|
||||
V(Isolate_sendOOB, 2) \
|
||||
|
|
|
@ -11,6 +11,7 @@ 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';
|
||||
|
||||
|
@ -130,11 +131,12 @@ Uri _resolvePackageUri(Uri uri) {
|
|||
_log('Resolving package with uri path: ${uri.path}');
|
||||
}
|
||||
var resolvedUri;
|
||||
if (_packageError != null) {
|
||||
final error = _packageError;
|
||||
if (error != null) {
|
||||
if (_traceLoading) {
|
||||
_log("Resolving package with pending resolution error: $_packageError");
|
||||
_log("Resolving package with pending resolution error: $error");
|
||||
}
|
||||
throw _packageError;
|
||||
throw error;
|
||||
} else {
|
||||
if (packageNameEnd < 0) {
|
||||
// Package URIs must have a path after the package name, even if it's
|
||||
|
@ -430,9 +432,67 @@ _parsePackagesFile(bool traceLoading, Uri packagesFile, List<int> 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 = <dynamic>[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 {
|
||||
var data = new File.fromUri(packagesFile).readAsBytesSync();
|
||||
final Uint8List data = File.fromUri(packagesFile).readAsBytesSync();
|
||||
if (traceLoading) {
|
||||
_log("Loaded packages file from $packagesFile:\n"
|
||||
"${new String.fromCharCodes(data)}");
|
||||
|
@ -446,39 +506,49 @@ _loadPackagesFile(bool traceLoading, Uri packagesFile) {
|
|||
}
|
||||
}
|
||||
|
||||
_findPackagesFile(bool traceLoading, Uri base) {
|
||||
_findPackagesConfiguration(bool traceLoading, Uri base) {
|
||||
try {
|
||||
// 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");
|
||||
// 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");
|
||||
if (traceLoading) {
|
||||
_log("Checking for $packagesFile file.");
|
||||
}
|
||||
var exists = new File.fromUri(packagesFile).existsSync();
|
||||
exists = File.fromUri(packagesFile).existsSync();
|
||||
if (traceLoading) {
|
||||
_log("$packagesFile exists: $exists");
|
||||
}
|
||||
if (exists) {
|
||||
return _loadPackagesFile(traceLoading, packagesFile);
|
||||
}
|
||||
// Move up one level.
|
||||
prev = dir;
|
||||
dir = dir.parent;
|
||||
final parentDir = currentDir.parent;
|
||||
if (currentDir == parentDir) break;
|
||||
currentDir = parentDir;
|
||||
}
|
||||
|
||||
// No .packages file was found.
|
||||
if (traceLoading) {
|
||||
_log("Could not resolve a package location from $base");
|
||||
_log("Could not resolve a package configuration from $base");
|
||||
}
|
||||
return "Could not resolve a package location for base at $base";
|
||||
return "Could not resolve a package configuration for base at $base";
|
||||
} catch (e, s) {
|
||||
if (traceLoading) {
|
||||
_log("Error loading packages: $e\n$s");
|
||||
|
@ -509,7 +579,7 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
|
|||
try {
|
||||
if (tag == -1) {
|
||||
if (resource.scheme == '' || resource.scheme == 'file') {
|
||||
return _findPackagesFile(traceLoading, resource);
|
||||
return _findPackagesConfiguration(traceLoading, resource);
|
||||
} else {
|
||||
return "Unsupported scheme used to locate .packages file:'$resource'.";
|
||||
}
|
||||
|
@ -580,6 +650,9 @@ 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) {
|
||||
|
|
|
@ -48,7 +48,6 @@ class VMLibraryHooks {
|
|||
// Implementation of package root/map provision.
|
||||
static var packageRootString;
|
||||
static var packageConfigString;
|
||||
static var packageRootUriFuture;
|
||||
static var packageConfigUriFuture;
|
||||
static var resolvePackageUriFuture;
|
||||
|
||||
|
|
|
@ -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.
|
||||
var readyMessage = new 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.
|
||||
final readyMessage = 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,7 +343,6 @@ class Isolate {
|
|||
}
|
||||
|
||||
static bool _packageSupported() =>
|
||||
(VMLibraryHooks.packageRootUriFuture != null) &&
|
||||
(VMLibraryHooks.packageConfigUriFuture != null) &&
|
||||
(VMLibraryHooks.resolvePackageUriFuture != null);
|
||||
|
||||
|
@ -355,46 +354,33 @@ class Isolate {
|
|||
SendPort onError,
|
||||
String debugName}) async {
|
||||
// `paused` isn't handled yet.
|
||||
RawReceivePort readyPort;
|
||||
// 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();
|
||||
try {
|
||||
// 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);
|
||||
_spawnFunction(readyPort.sendPort, script.toString(), entryPoint, message,
|
||||
paused, errorsAreFatal, onExit, onError, packageConfig, debugName);
|
||||
return await _spawnCommon(readyPort);
|
||||
} catch (e, st) {
|
||||
if (readyPort != null) {
|
||||
readyPort.close();
|
||||
}
|
||||
readyPort.close();
|
||||
return await new Future<Isolate>.error(e, st);
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +397,6 @@ class Isolate {
|
|||
Uri packageConfig,
|
||||
bool automaticPackageResolution: false,
|
||||
String debugName}) async {
|
||||
RawReceivePort readyPort;
|
||||
if (environment != null) {
|
||||
throw new UnimplementedError("environment");
|
||||
}
|
||||
|
@ -434,38 +419,30 @@ 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(),
|
||||
|
@ -478,20 +455,17 @@ class Isolate {
|
|||
checked,
|
||||
null,
|
||||
/* environment */
|
||||
packageRootString,
|
||||
packageConfigString,
|
||||
debugName);
|
||||
return await _spawnCommon(readyPort);
|
||||
} catch (e) {
|
||||
if (readyPort != null) {
|
||||
readyPort.close();
|
||||
}
|
||||
readyPort.close();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Isolate> _spawnCommon(RawReceivePort readyPort) {
|
||||
Completer completer = new Completer<Isolate>.sync();
|
||||
final completer = new Completer<Isolate>.sync();
|
||||
readyPort.handler = (readyMessage) {
|
||||
readyPort.close();
|
||||
if (readyMessage is List && readyMessage.length == 2) {
|
||||
|
@ -536,7 +510,6 @@ class Isolate {
|
|||
bool errorsAreFatal,
|
||||
SendPort onExit,
|
||||
SendPort onError,
|
||||
String packageRoot,
|
||||
String packageConfig,
|
||||
String debugName) native "Isolate_spawnFunction";
|
||||
|
||||
|
@ -551,7 +524,6 @@ class Isolate {
|
|||
bool errorsAreFatal,
|
||||
bool checked,
|
||||
List environment,
|
||||
String packageRoot,
|
||||
String packageConfig,
|
||||
String debugName) native "Isolate_spawnUri";
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ 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';
|
||||
|
||||
|
@ -430,9 +431,67 @@ _parsePackagesFile(bool traceLoading, Uri packagesFile, List<int> 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 = <dynamic>[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 {
|
||||
var data = new File.fromUri(packagesFile).readAsBytesSync();
|
||||
final Uint8List data = File.fromUri(packagesFile).readAsBytesSync();
|
||||
if (traceLoading) {
|
||||
_log("Loaded packages file from $packagesFile:\n"
|
||||
"${new String.fromCharCodes(data)}");
|
||||
|
@ -446,39 +505,49 @@ _loadPackagesFile(bool traceLoading, Uri packagesFile) {
|
|||
}
|
||||
}
|
||||
|
||||
_findPackagesFile(bool traceLoading, Uri base) {
|
||||
_findPackagesConfiguration(bool traceLoading, Uri base) {
|
||||
try {
|
||||
// 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");
|
||||
// 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");
|
||||
if (traceLoading) {
|
||||
_log("Checking for $packagesFile file.");
|
||||
}
|
||||
var exists = new File.fromUri(packagesFile).existsSync();
|
||||
exists = File.fromUri(packagesFile).existsSync();
|
||||
if (traceLoading) {
|
||||
_log("$packagesFile exists: $exists");
|
||||
}
|
||||
if (exists) {
|
||||
return _loadPackagesFile(traceLoading, packagesFile);
|
||||
}
|
||||
// Move up one level.
|
||||
prev = dir;
|
||||
dir = dir.parent;
|
||||
final parentDir = currentDir.parent;
|
||||
if (currentDir == parentDir) break;
|
||||
currentDir = parentDir;
|
||||
}
|
||||
|
||||
// No .packages file was found.
|
||||
if (traceLoading) {
|
||||
_log("Could not resolve a package location from $base");
|
||||
_log("Could not resolve a package configuration from $base");
|
||||
}
|
||||
return "Could not resolve a package location for base at $base";
|
||||
return "Could not resolve a package configuration for base at $base";
|
||||
} catch (e, s) {
|
||||
if (traceLoading) {
|
||||
_log("Error loading packages: $e\n$s");
|
||||
|
@ -509,7 +578,7 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
|
|||
try {
|
||||
if (tag == -1) {
|
||||
if (resource.scheme == '' || resource.scheme == 'file') {
|
||||
return _findPackagesFile(traceLoading, resource);
|
||||
return _findPackagesConfiguration(traceLoading, resource);
|
||||
} else {
|
||||
return "Unsupported scheme used to locate .packages file:'$resource'.";
|
||||
}
|
||||
|
@ -580,6 +649,9 @@ 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) {
|
||||
|
|
|
@ -52,7 +52,6 @@ class VMLibraryHooks {
|
|||
// Implementation of package root/map provision.
|
||||
static var packageRootString;
|
||||
static var packageConfigString;
|
||||
static var packageRootUriFuture;
|
||||
static var packageConfigUriFuture;
|
||||
static var resolvePackageUriFuture;
|
||||
|
||||
|
|
|
@ -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.
|
||||
var readyMessage = new List<Object?>.filled(2, null);
|
||||
final readyMessage = List<Object?>.filled(2, null);
|
||||
readyMessage[0] = controlPort.sendPort;
|
||||
readyMessage[1] = capabilities;
|
||||
|
||||
|
@ -342,7 +342,6 @@ class Isolate {
|
|||
}
|
||||
|
||||
static bool _packageSupported() =>
|
||||
(VMLibraryHooks.packageRootUriFuture != null) &&
|
||||
(VMLibraryHooks.packageConfigUriFuture != null) &&
|
||||
(VMLibraryHooks.resolvePackageUriFuture != null);
|
||||
|
||||
|
@ -376,18 +375,8 @@ class Isolate {
|
|||
|
||||
final RawReceivePort readyPort = new RawReceivePort();
|
||||
try {
|
||||
_spawnFunction(
|
||||
readyPort.sendPort,
|
||||
script.toString(),
|
||||
entryPoint,
|
||||
message,
|
||||
paused,
|
||||
errorsAreFatal,
|
||||
onExit,
|
||||
onError,
|
||||
null,
|
||||
packageConfig,
|
||||
debugName);
|
||||
_spawnFunction(readyPort.sendPort, script.toString(), entryPoint, message,
|
||||
paused, errorsAreFatal, onExit, onError, packageConfig, debugName);
|
||||
return await _spawnCommon(readyPort);
|
||||
} catch (e, st) {
|
||||
readyPort.close();
|
||||
|
@ -430,24 +419,17 @@ class Isolate {
|
|||
}
|
||||
}
|
||||
// Resolve the uri against the current isolate's root Uri first.
|
||||
var spawnedUri = _rootUri!.resolveUri(uri);
|
||||
final Uri spawnedUri = _rootUri!.resolveUri(uri);
|
||||
|
||||
// Inherit this isolate's package resolution setup if not overridden.
|
||||
if (!automaticPackageResolution &&
|
||||
(packageRoot == null) &&
|
||||
(packageConfig == null)) {
|
||||
if (!automaticPackageResolution && 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) {
|
||||
if (packageConfig != null) {
|
||||
// Avoid calling resolvePackageUri if not strictly necessary in case
|
||||
// the API is not supported.
|
||||
if (packageConfig.isScheme("package")) {
|
||||
|
@ -456,8 +438,7 @@ class Isolate {
|
|||
}
|
||||
|
||||
// The VM will invoke [_startIsolate] and not `main`.
|
||||
var packageRootString = packageRoot?.toString();
|
||||
var packageConfigString = packageConfig?.toString();
|
||||
final packageConfigString = packageConfig?.toString();
|
||||
|
||||
final RawReceivePort readyPort = new RawReceivePort();
|
||||
try {
|
||||
|
@ -473,7 +454,6 @@ class Isolate {
|
|||
checked,
|
||||
null,
|
||||
/* environment */
|
||||
packageRootString,
|
||||
packageConfigString,
|
||||
debugName);
|
||||
return await _spawnCommon(readyPort);
|
||||
|
@ -529,7 +509,6 @@ class Isolate {
|
|||
bool errorsAreFatal,
|
||||
SendPort? onExit,
|
||||
SendPort? onError,
|
||||
String? packageRoot,
|
||||
String? packageConfig,
|
||||
String? debugName) native "Isolate_spawnFunction";
|
||||
|
||||
|
@ -544,7 +523,6 @@ class Isolate {
|
|||
bool errorsAreFatal,
|
||||
bool? checked,
|
||||
List? environment,
|
||||
String? packageRoot,
|
||||
String? packageConfig,
|
||||
String? debugName) native "Isolate_spawnUri";
|
||||
|
||||
|
|
164
tests/lib/isolate/spawn_uri__package_uri__test.dart
Normal file
164
tests/lib/isolate/spawn_uri__package_uri__test.dart
Normal file
|
@ -0,0 +1,164 @@
|
|||
// 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=<packages|package_config>
|
||||
for (final runWithPackagesArg in const [true, false]) {
|
||||
// Run the isolate with or without
|
||||
// Isolate.spawnUri(..., packageConfig: <packages|package_config>)
|
||||
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<ProcessResult> run(String executable, List<String> 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<String> 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<String> args) async {
|
||||
io.exitCode = 1;
|
||||
|
||||
final rp = ReceivePort();
|
||||
final uri = Uri.parse('$spawnUri');
|
||||
final isolateArgs = <String>['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;
|
||||
}
|
||||
''';
|
|
@ -24,6 +24,9 @@ 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
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ 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.
|
||||
|
|
164
tests/lib_2/isolate/spawn_uri__package_uri__test.dart
Normal file
164
tests/lib_2/isolate/spawn_uri__package_uri__test.dart
Normal file
|
@ -0,0 +1,164 @@
|
|||
// 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=<packages|package_config>
|
||||
for (final runWithPackagesArg in const [true, false]) {
|
||||
// Run the isolate with or without
|
||||
// Isolate.spawnUri(..., packageConfig: <packages|package_config>)
|
||||
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<ProcessResult> run(String executable, List<String> 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<String> 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<String> args) async {
|
||||
io.exitCode = 1;
|
||||
|
||||
final rp = ReceivePort();
|
||||
final uri = Uri.parse('$spawnUri');
|
||||
final isolateArgs = <String>['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;
|
||||
}
|
||||
''';
|
|
@ -24,6 +24,9 @@ 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
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ 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.
|
||||
|
|
Loading…
Reference in a new issue