[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: I642dfb89f82b3f2c1613e443850bf0b4fb91f4a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144766
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Martin Kustermann 2020-04-27 12:54:38 +00:00 committed by commit-bot@chromium.org
parent d5310cb2d6
commit b112aa0d8b
18 changed files with 632 additions and 236 deletions

View file

@ -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;

View file

@ -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_);

View file

@ -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_;

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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));

View file

@ -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) \

View file

@ -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) {

View file

@ -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;

View file

@ -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";

View file

@ -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) {

View file

@ -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;

View file

@ -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";

View file

@ -0,0 +1,163 @@
// 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]) {
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: cwd);
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.parse("$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;
}
''';

View file

@ -0,0 +1,163 @@
// 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]) {
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(' ')}');
cwd ??= Directory.current.absolute.path;
final result = await Process.run(executable, ['--trace-loading', ...args],
workingDirectory: cwd);
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.parse("$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;
}
''';

View file

@ -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

View file

@ -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.