[vm/isolate] Make Isolate.resolveUri() work for both .packages and dart_tool/package_config.json

Change-Id: I0f923e65f6bb00def2f96704bc51aa751d55ce7e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145803
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Martin Kustermann 2020-05-01 14:13:01 +00:00 committed by commit-bot@chromium.org
parent 59467b2232
commit a99f7aef6e
11 changed files with 543 additions and 712 deletions

View file

@ -145,7 +145,7 @@ Uri _resolvePackageUri(Uri uri) {
"'package:${uri.path}/', not 'package:${uri.path}'";
}
var packageName = uri.path.substring(0, packageNameEnd);
var mapping = _packageMap[packageName];
final mapping = _packageMap[packageName];
if (_traceLoading) {
_log("Mapped '$packageName' package to '$mapping'");
}
@ -206,247 +206,81 @@ void _requestPackagesMap(Uri packageConfig) {
}
}
// Handling of packages requests. Finding and parsing of .packages file or
// packages/ directories.
const _LF = 0x0A;
const _CR = 0x0D;
const _SPACE = 0x20;
const _HASH = 0x23;
const _DOT = 0x2E;
const _COLON = 0x3A;
const _DEL = 0x7F;
// The values go from ' ' to DEL and `x` means disallowed.
const String _invalidPackageNameChars =
'x.xx.x.........x..........x.x.xx...........................xxxx.x..........................xxx.x';
const _invalidPackageNameChars = const [
true, // space
false, // !
true, // "
true, // #
false, // $
true, // %
false, // &
false, // '
false, // (
false, // )
false, // *
false, // +
false, // ,
false, // -
false, // .
true, // /
false, // 0
false, // 1
false, // 2
false, // 3
false, // 4
false, // 5
false, // 6
false, // 7
false, // 8
false, // 9
true, // :
false, // ;
true, // <
false, // =
true, // >
true, // ?
false, // @
false, // A
false, // B
false, // C
false, // D
false, // E
false, // F
false, // G
false, // H
false, // I
false, // J
false, // K
false, // L
false, // M
false, // N
false, // O
false, // P
false, // Q
false, // R
false, // S
false, // T
false, // U
false, // V
false, // W
false, // X
false, // Y
false, // Z
true, // [
true, // \
true, // ]
true, // ^
false, // _
true, // `
false, // a
false, // b
false, // c
false, // d
false, // e
false, // f
false, // g
false, // h
false, // i
false, // j
false, // k
false, // l
false, // m
false, // n
false, // o
false, // p
false, // q
false, // r
false, // s
false, // t
false, // u
false, // v
false, // w
false, // x
false, // y
false, // z
true, // {
true, // |
true, // }
false, // ~
true, // DEL
];
bool _isValidPackageName(String packageName) {
const space = 0x20;
const del = 0x7F;
const dot = 0x2e;
const lowerX = 0x78;
for (int i = 0; i < packageName.length; ++i) {
final int char = packageName.codeUnitAt(i);
if (char < space || del < char) {
return false;
}
final int allowed = _invalidPackageNameChars.codeUnitAt(char - space);
assert(allowed == dot || allowed == lowerX);
if (allowed == lowerX) {
return false;
}
}
return true;
}
_parsePackagesFile(bool traceLoading, Uri packagesFile, List<int> data) {
_parsePackagesFile(bool traceLoading, Uri packagesFile, String data) {
// The first entry contains the location of the identified .packages file
// instead of a mapping.
var result = [packagesFile.toString(), null];
var index = 0;
var len = data.length;
while (index < len) {
var start = index;
var char = data[index];
if ((char == _CR) || (char == _LF)) {
// Skipping empty lines.
index++;
final List result = [packagesFile.toString(), null];
final lines = LineSplitter.split(data);
for (String line in lines) {
final hashIndex = line.indexOf('#');
if (hashIndex == 0) {
continue;
}
if (hashIndex > 0) {
line = line.substring(0, hashIndex);
}
line = line.trimRight();
if (line.isEmpty) {
continue;
}
// Identify split within the line and end of the line.
var separator = -1;
var end = len;
// Verifying validity of package name while scanning the line.
var nonDot = false;
var invalidPackageName = false;
// Scan to the end of the line or data.
while (index < len) {
char = data[index++];
// If we have not reached the separator yet, determine whether we are
// scanning legal package name characters.
if (separator == -1) {
if ((char == _COLON)) {
// The first colon on a line is the separator between package name and
// related URI.
separator = index - 1;
} else {
// Still scanning the package name part. Check for the validity of
// the characters.
nonDot = nonDot || (char != _DOT);
invalidPackageName = invalidPackageName ||
(char < _SPACE) ||
(char > _DEL) ||
_invalidPackageNameChars[char - _SPACE];
}
}
// Identify end of line.
if ((char == _CR) || (char == _LF)) {
end = index - 1;
break;
}
}
// No further handling needed for comment lines.
if (data[start] == _HASH) {
if (traceLoading) {
_log("Skipping comment in $packagesFile:\n"
"${new String.fromCharCodes(data, start, end)}");
}
continue;
}
// Check for a badly formatted line, starting with a ':'.
if (separator == start) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Line starts with ':' in $packagesFile:\n"
"$line");
}
return "Missing package name in $packagesFile:\n"
"$line";
}
// Ensure there is a separator on the line.
if (separator == -1) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Line has no ':' in $packagesFile:\n"
"$line");
}
return "Missing ':' separator in $packagesFile:\n"
"$line";
}
var packageName = new String.fromCharCodes(data, start, separator);
// Check for valid package name.
if (invalidPackageName || !nonDot) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Invalid package name $packageName in $packagesFile");
}
return "Invalid package name '$packageName' in $packagesFile:\n"
"$line";
final colonIndex = line.indexOf(':');
if (colonIndex <= 0) {
return 'Line in "$packagesFile" should be of the format '
'`<package-name>:<path>" but was: "$line"';
}
final packageName = line.substring(0, colonIndex);
if (!_isValidPackageName(packageName)) {
return 'Package name in $packagesFile contains disallowed characters ('
'was: "$packageName")';
}
String packageUri = line.substring(colonIndex + 1);
if (traceLoading) {
_log("packageName: $packageName");
}
var packageUri = new String.fromCharCodes(data, separator + 1, end);
if (traceLoading) {
_log("original packageUri: $packageUri");
_log("packageUri: $packageUri");
}
// Ensure the package uri ends with a /.
if (!packageUri.endsWith("/")) {
packageUri = "$packageUri/";
if (!packageUri.endsWith('/')) {
packageUri += '/';
}
packageUri = packagesFile.resolve(packageUri).toString();
final resolvedPackageUri = packagesFile.resolve(packageUri).toString();
if (traceLoading) {
_log("mapping: $packageName -> $packageUri");
_log("mapping: $packageName -> $resolvedPackageUri");
}
result.add(packageName);
result.add(packageUri);
result.add(resolvedPackageUri);
}
if (traceLoading) {
_log("Parsed packages file at $packagesFile. Sending:\n$result");
}
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
@ -458,9 +292,8 @@ _loadPackageConfigFile(bool traceLoading, Uri packageConfig) {
// [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));
List _parsePackageConfig(bool traceLoading, Uri packageConfig, String data) {
final Map packageJson = json.decode(data);
final version = packageJson['configVersion'];
if (version != 2) {
throw 'The package configuration file has an unsupported version.';
@ -470,8 +303,9 @@ List _parsePackageConfig(
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'];
String rootUri = package['rootUri'];
if (!rootUri.endsWith('/')) rootUri += '/';
final String packageName = package['name'];
final String packageUri = package['packageUri'];
final Uri resolvedRootUri = packageConfig.resolve(rootUri);
final Uri resolvedPackageUri = packageUri != null
@ -481,31 +315,19 @@ List _parsePackageConfig(
!'$resolvedPackageUri'.contains('$resolvedRootUri')) {
throw 'The resolved "packageUri" is not a subdirectory of the "rootUri".';
}
result.add(name);
if (!_isValidPackageName(packageName)) {
throw 'Package name in $packageConfig contains disallowed characters ('
'was: "$packageName")';
}
result.add(packageName);
result.add(resolvedPackageUri.toString());
if (traceLoading) {
_log('Resolved package $name to be at $resolvedPackageUri');
_log('Resolved package "$packageName" to be at $resolvedPackageUri');
}
}
return result;
}
_loadPackagesFile(bool traceLoading, Uri packagesFile) {
try {
final Uint8List data = File.fromUri(packagesFile).readAsBytesSync();
if (traceLoading) {
_log("Loaded packages file from $packagesFile:\n"
"${new String.fromCharCodes(data)}");
}
return _parsePackagesFile(traceLoading, packagesFile, data);
} catch (e, s) {
if (traceLoading) {
_log("Error loading packages: $e\n$s");
}
return "Uncaught error ($e) loading packages file.";
}
}
_findPackagesConfiguration(bool traceLoading, Uri base) {
try {
// Walk up the directory hierarchy to check for the existence of either one
@ -521,24 +343,36 @@ _findPackagesConfiguration(bool traceLoading, Uri base) {
if (traceLoading) {
_log("Checking for $packageConfig file.");
}
bool exists = File.fromUri(packageConfig).existsSync();
File file = File.fromUri(packageConfig);
bool exists = file.existsSync();
if (traceLoading) {
_log("$packageConfig exists: $exists");
}
if (exists) {
return _loadPackageConfigFile(traceLoading, packageConfig);
final Uint8List bytes = file.readAsBytesSync();
final data = utf8.decode(bytes);
if (traceLoading) {
_log("Loaded package config file from $packageConfig:$data\n");
}
return _parsePackageConfig(traceLoading, packageConfig, data);
}
final packagesFile = dirUri.resolve(".packages");
if (traceLoading) {
_log("Checking for $packagesFile file.");
}
exists = File.fromUri(packagesFile).existsSync();
file = File.fromUri(packagesFile);
exists = file.existsSync();
if (traceLoading) {
_log("$packagesFile exists: $exists");
}
if (exists) {
return _loadPackagesFile(traceLoading, packagesFile);
final Uint8List bytes = file.readAsBytesSync();
final String data = utf8.decode(bytes);
if (traceLoading) {
_log("Loaded packages file from $packagesFile:\n$data");
}
return _parsePackagesFile(traceLoading, packagesFile, data);
}
final parentDir = currentDir.parent;
if (dirUri == parentDir.uri) break;
@ -557,22 +391,55 @@ _findPackagesConfiguration(bool traceLoading, Uri base) {
}
}
_loadPackagesData(traceLoading, resource) {
try {
var data = resource.data;
var mime = data.mimeType;
if (mime != "text/plain") {
throw "MIME-type must be text/plain: $mime given.";
int _indexOfFirstNonWhitespaceCharacter(String data) {
// Whitespace characters ignored in JSON spec:
// https://tools.ietf.org/html/rfc7159
const tab = 0x09;
const lf = 0x0A;
const cr = 0x0D;
const space = 0x20;
int index = 0;
while (index < data.length) {
final int char = data.codeUnitAt(index);
if (char != lf && char != cr && char != space && char != tab) {
break;
}
var charset = data.charset;
if ((charset != "utf-8") && (charset != "US-ASCII")) {
// The C++ portion of the embedder assumes UTF-8.
throw "Only utf-8 or US-ASCII encodings are supported: $charset given.";
}
return _parsePackagesFile(traceLoading, resource, data.contentAsBytes());
} catch (e) {
return "Uncaught error ($e) loading packages data.";
index++;
}
return index;
}
bool _canBeValidJson(String data) {
const int openCurly = 0x7B;
final int index = _indexOfFirstNonWhitespaceCharacter(data);
return index < data.length && data.codeUnitAt(index) == openCurly;
}
_parsePackageConfiguration(bool traceLoading, Uri resource, Uint8List bytes) {
try {
final data = utf8.decode(bytes);
if (_canBeValidJson(data)) {
return _parsePackageConfig(traceLoading, resource, data);
} else {
return _parsePackagesFile(traceLoading, resource, data);
}
} catch (e) {
return "The resource '$resource' is neither a valid '.packages' file nor "
"a valid '.dart_tool/package_config.json' file.";
}
}
bool _isValidUtf8DataUrl(UriData data) {
final mime = data.mimeType;
if (mime != "text/plain") {
return false;
}
final charset = data.charset;
if (charset != "utf-8" && charset != "US-ASCII") {
return false;
}
return true;
}
_handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
@ -587,19 +454,25 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
if (traceLoading) {
_log("Handling load of packages map: '$resource'.");
}
Uint8List bytes;
if (resource.scheme == '' || resource.scheme == 'file') {
var exists = new File.fromUri(resource).existsSync();
if (exists) {
return _loadPackagesFile(traceLoading, resource);
} else {
return "Packages file '$resource' not found.";
final file = File.fromUri(resource);
if (!file.existsSync()) {
return "Packages file '$resource' does not exit.";
}
bytes = file.readAsBytesSync();
} else if (resource.scheme == 'data') {
return _loadPackagesData(traceLoading, resource);
final uriData = resource.data;
if (!_isValidUtf8DataUrl(uriData)) {
return "The data resource '$resource' must have a 'text/plain' mime "
"type and a 'utf-8' or 'US-ASCII' charset.";
}
bytes = uriData.contentAsBytes();
} else {
return "Unknown scheme (${resource.scheme}) for package file at "
"'$resource'.";
}
return _parsePackageConfiguration(traceLoading, resource, bytes);
} else {
return "Unknown packages request tag: $tag for '$resource'.";
}
@ -750,7 +623,7 @@ Future<Uri> _resolvePackageUriFuture(Uri packageUri) {
resolvedUri = _resolvePackageUri(packageUri);
} catch (e, s) {
if (_traceLoading) {
_log("Exception when resolving package URI: $packageUri");
_log("Exception when resolving package URI: $packageUri:\n$e\n$s");
}
resolvedUri = null;
}

View file

@ -165,7 +165,7 @@ Uri _resolvePackageUri(Uri uri) {
}
void _requestPackagesMap(Uri? packageConfig) {
var msg = null;
dynamic msg = null;
if (packageConfig != null) {
// Explicitly specified .packages path.
msg = _handlePackagesRequest(_traceLoading, -2, packageConfig);
@ -205,247 +205,81 @@ void _requestPackagesMap(Uri? packageConfig) {
}
}
// Handling of packages requests. Finding and parsing of .packages file or
// packages/ directories.
const _LF = 0x0A;
const _CR = 0x0D;
const _SPACE = 0x20;
const _HASH = 0x23;
const _DOT = 0x2E;
const _COLON = 0x3A;
const _DEL = 0x7F;
// The values go from ' ' to DEL and `x` means disallowed.
const String _invalidPackageNameChars =
'x.xx.x.........x..........x.x.xx...........................xxxx.x..........................xxx.x';
const _invalidPackageNameChars = const [
true, // space
false, // !
true, // "
true, // #
false, // $
true, // %
false, // &
false, // '
false, // (
false, // )
false, // *
false, // +
false, // ,
false, // -
false, // .
true, // /
false, // 0
false, // 1
false, // 2
false, // 3
false, // 4
false, // 5
false, // 6
false, // 7
false, // 8
false, // 9
true, // :
false, // ;
true, // <
false, // =
true, // >
true, // ?
false, // @
false, // A
false, // B
false, // C
false, // D
false, // E
false, // F
false, // G
false, // H
false, // I
false, // J
false, // K
false, // L
false, // M
false, // N
false, // O
false, // P
false, // Q
false, // R
false, // S
false, // T
false, // U
false, // V
false, // W
false, // X
false, // Y
false, // Z
true, // [
true, // \
true, // ]
true, // ^
false, // _
true, // `
false, // a
false, // b
false, // c
false, // d
false, // e
false, // f
false, // g
false, // h
false, // i
false, // j
false, // k
false, // l
false, // m
false, // n
false, // o
false, // p
false, // q
false, // r
false, // s
false, // t
false, // u
false, // v
false, // w
false, // x
false, // y
false, // z
true, // {
true, // |
true, // }
false, // ~
true, // DEL
];
bool _isValidPackageName(String packageName) {
const space = 0x20;
const del = 0x7F;
const dot = 0x2e;
const lowerX = 0x78;
for (int i = 0; i < packageName.length; ++i) {
final int char = packageName.codeUnitAt(i);
if (char < space || del < char) {
return false;
}
final int allowed = _invalidPackageNameChars.codeUnitAt(char - space);
assert(allowed == dot || allowed == lowerX);
if (allowed == lowerX) {
return false;
}
}
return true;
}
_parsePackagesFile(bool traceLoading, Uri packagesFile, List<int> data) {
_parsePackagesFile(bool traceLoading, Uri packagesFile, String data) {
// The first entry contains the location of the identified .packages file
// instead of a mapping.
var result = [packagesFile.toString(), null];
var index = 0;
var len = data.length;
while (index < len) {
var start = index;
var char = data[index];
if ((char == _CR) || (char == _LF)) {
// Skipping empty lines.
index++;
final List result = [packagesFile.toString(), null];
final lines = LineSplitter.split(data);
for (String line in lines) {
final hashIndex = line.indexOf('#');
if (hashIndex == 0) {
continue;
}
if (hashIndex > 0) {
line = line.substring(0, hashIndex);
}
line = line.trimRight();
if (line.isEmpty) {
continue;
}
// Identify split within the line and end of the line.
var separator = -1;
var end = len;
// Verifying validity of package name while scanning the line.
var nonDot = false;
var invalidPackageName = false;
// Scan to the end of the line or data.
while (index < len) {
char = data[index++];
// If we have not reached the separator yet, determine whether we are
// scanning legal package name characters.
if (separator == -1) {
if ((char == _COLON)) {
// The first colon on a line is the separator between package name and
// related URI.
separator = index - 1;
} else {
// Still scanning the package name part. Check for the validity of
// the characters.
nonDot = nonDot || (char != _DOT);
invalidPackageName = invalidPackageName ||
(char < _SPACE) ||
(char > _DEL) ||
_invalidPackageNameChars[char - _SPACE];
}
}
// Identify end of line.
if ((char == _CR) || (char == _LF)) {
end = index - 1;
break;
}
}
// No further handling needed for comment lines.
if (data[start] == _HASH) {
if (traceLoading) {
_log("Skipping comment in $packagesFile:\n"
"${new String.fromCharCodes(data, start, end)}");
}
continue;
}
// Check for a badly formatted line, starting with a ':'.
if (separator == start) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Line starts with ':' in $packagesFile:\n"
"$line");
}
return "Missing package name in $packagesFile:\n"
"$line";
}
// Ensure there is a separator on the line.
if (separator == -1) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Line has no ':' in $packagesFile:\n"
"$line");
}
return "Missing ':' separator in $packagesFile:\n"
"$line";
}
var packageName = new String.fromCharCodes(data, start, separator);
// Check for valid package name.
if (invalidPackageName || !nonDot) {
var line = new String.fromCharCodes(data, start, end);
if (traceLoading) {
_log("Invalid package name $packageName in $packagesFile");
}
return "Invalid package name '$packageName' in $packagesFile:\n"
"$line";
final colonIndex = line.indexOf(':');
if (colonIndex <= 0) {
return 'Line in "$packagesFile" should be of the format '
'`<package-name>:<path>" but was: "$line"';
}
final packageName = line.substring(0, colonIndex);
if (!_isValidPackageName(packageName)) {
return 'Package name in $packagesFile contains disallowed characters ('
'was: "$packageName")';
}
String packageUri = line.substring(colonIndex + 1);
if (traceLoading) {
_log("packageName: $packageName");
}
var packageUri = new String.fromCharCodes(data, separator + 1, end);
if (traceLoading) {
_log("original packageUri: $packageUri");
_log("packageUri: $packageUri");
}
// Ensure the package uri ends with a /.
if (!packageUri.endsWith("/")) {
packageUri = "$packageUri/";
if (!packageUri.endsWith('/')) {
packageUri += '/';
}
packageUri = packagesFile.resolve(packageUri).toString();
final resolvedPackageUri = packagesFile.resolve(packageUri).toString();
if (traceLoading) {
_log("mapping: $packageName -> $packageUri");
_log("mapping: $packageName -> $resolvedPackageUri");
}
result.add(packageName);
result.add(packageUri);
result.add(resolvedPackageUri);
}
if (traceLoading) {
_log("Parsed packages file at $packagesFile. Sending:\n$result");
}
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
@ -457,9 +291,8 @@ _loadPackageConfigFile(bool traceLoading, Uri packageConfig) {
// [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));
List _parsePackageConfig(bool traceLoading, Uri packageConfig, String data) {
final Map packageJson = json.decode(data);
final version = packageJson['configVersion'];
if (version != 2) {
throw 'The package configuration file has an unsupported version.';
@ -469,8 +302,9 @@ List _parsePackageConfig(
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'];
String rootUri = package['rootUri'];
if (!rootUri.endsWith('/')) rootUri += '/';
final String packageName = package['name'];
final String? packageUri = package['packageUri'];
final Uri resolvedRootUri = packageConfig.resolve(rootUri);
final Uri resolvedPackageUri = packageUri != null
@ -480,31 +314,19 @@ List _parsePackageConfig(
!'$resolvedPackageUri'.contains('$resolvedRootUri')) {
throw 'The resolved "packageUri" is not a subdirectory of the "rootUri".';
}
result.add(name);
if (!_isValidPackageName(packageName)) {
throw 'Package name in $packageConfig contains disallowed characters ('
'was: "$packageName")';
}
result.add(packageName);
result.add(resolvedPackageUri.toString());
if (traceLoading) {
_log('Resolved package $name to be at $resolvedPackageUri');
_log('Resolved package "$packageName" to be at $resolvedPackageUri');
}
}
return result;
}
_loadPackagesFile(bool traceLoading, Uri packagesFile) {
try {
final Uint8List data = File.fromUri(packagesFile).readAsBytesSync();
if (traceLoading) {
_log("Loaded packages file from $packagesFile:\n"
"${new String.fromCharCodes(data)}");
}
return _parsePackagesFile(traceLoading, packagesFile, data);
} catch (e, s) {
if (traceLoading) {
_log("Error loading packages: $e\n$s");
}
return "Uncaught error ($e) loading packages file.";
}
}
_findPackagesConfiguration(bool traceLoading, Uri base) {
try {
// Walk up the directory hierarchy to check for the existence of either one
@ -520,24 +342,36 @@ _findPackagesConfiguration(bool traceLoading, Uri base) {
if (traceLoading) {
_log("Checking for $packageConfig file.");
}
bool exists = File.fromUri(packageConfig).existsSync();
File file = File.fromUri(packageConfig);
bool exists = file.existsSync();
if (traceLoading) {
_log("$packageConfig exists: $exists");
}
if (exists) {
return _loadPackageConfigFile(traceLoading, packageConfig);
final Uint8List bytes = file.readAsBytesSync();
final data = utf8.decode(bytes);
if (traceLoading) {
_log("Loaded package config file from $packageConfig:$data\n");
}
return _parsePackageConfig(traceLoading, packageConfig, data);
}
final packagesFile = dirUri.resolve(".packages");
if (traceLoading) {
_log("Checking for $packagesFile file.");
}
exists = File.fromUri(packagesFile).existsSync();
file = File.fromUri(packagesFile);
exists = file.existsSync();
if (traceLoading) {
_log("$packagesFile exists: $exists");
}
if (exists) {
return _loadPackagesFile(traceLoading, packagesFile);
final Uint8List bytes = file.readAsBytesSync();
final String data = utf8.decode(bytes);
if (traceLoading) {
_log("Loaded packages file from $packagesFile:\n$data");
}
return _parsePackagesFile(traceLoading, packagesFile, data);
}
final parentDir = currentDir.parent;
if (dirUri == parentDir.uri) break;
@ -556,22 +390,55 @@ _findPackagesConfiguration(bool traceLoading, Uri base) {
}
}
_loadPackagesData(traceLoading, resource) {
try {
var data = resource.data;
var mime = data.mimeType;
if (mime != "text/plain") {
throw "MIME-type must be text/plain: $mime given.";
int _indexOfFirstNonWhitespaceCharacter(String data) {
// Whitespace characters ignored in JSON spec:
// https://tools.ietf.org/html/rfc7159
const tab = 0x09;
const lf = 0x0A;
const cr = 0x0D;
const space = 0x20;
int index = 0;
while (index < data.length) {
final int char = data.codeUnitAt(index);
if (char != lf && char != cr && char != space && char != tab) {
break;
}
var charset = data.charset;
if ((charset != "utf-8") && (charset != "US-ASCII")) {
// The C++ portion of the embedder assumes UTF-8.
throw "Only utf-8 or US-ASCII encodings are supported: $charset given.";
}
return _parsePackagesFile(traceLoading, resource, data.contentAsBytes());
} catch (e) {
return "Uncaught error ($e) loading packages data.";
index++;
}
return index;
}
bool _canBeValidJson(String data) {
const int openCurly = 0x7B;
final int index = _indexOfFirstNonWhitespaceCharacter(data);
return index < data.length && data.codeUnitAt(index) == openCurly;
}
_parsePackageConfiguration(bool traceLoading, Uri resource, Uint8List bytes) {
try {
final data = utf8.decode(bytes);
if (_canBeValidJson(data)) {
return _parsePackageConfig(traceLoading, resource, data);
} else {
return _parsePackagesFile(traceLoading, resource, data);
}
} catch (e) {
return "The resource '$resource' is neither a valid '.packages' file nor "
"a valid '.dart_tool/package_config.json' file.";
}
}
bool _isValidUtf8DataUrl(UriData data) {
final mime = data.mimeType;
if (mime != "text/plain") {
return false;
}
final charset = data.charset;
if (charset != "utf-8" && charset != "US-ASCII") {
return false;
}
return true;
}
_handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
@ -586,19 +453,25 @@ _handlePackagesRequest(bool traceLoading, int tag, Uri resource) {
if (traceLoading) {
_log("Handling load of packages map: '$resource'.");
}
late Uint8List bytes;
if (resource.scheme == '' || resource.scheme == 'file') {
var exists = new File.fromUri(resource).existsSync();
if (exists) {
return _loadPackagesFile(traceLoading, resource);
} else {
return "Packages file '$resource' not found.";
final file = File.fromUri(resource);
if (!file.existsSync()) {
return "Packages file '$resource' does not exit.";
}
bytes = file.readAsBytesSync();
} else if (resource.scheme == 'data') {
return _loadPackagesData(traceLoading, resource);
final uriData = resource.data!;
if (!_isValidUtf8DataUrl(uriData)) {
return "The data resource '$resource' must have a 'text/plain' mime "
"type and a 'utf-8' or 'US-ASCII' charset.";
}
bytes = uriData.contentAsBytes();
} else {
return "Unknown scheme (${resource.scheme}) for package file at "
"'$resource'.";
}
return _parsePackageConfiguration(traceLoading, resource, bytes);
} else {
return "Unknown packages request tag: $tag for '$resource'.";
}
@ -743,7 +616,7 @@ Future<Uri?> _resolvePackageUriFuture(Uri packageUri) {
resolvedUri = _resolvePackageUri(packageUri);
} catch (e, s) {
if (_traceLoading) {
_log("Exception when resolving package URI: $packageUri");
_log("Exception when resolving package URI: $packageUri:\n$e\n$s");
}
resolvedUri = null;
}

View file

@ -8,33 +8,26 @@
import 'dart:io';
import 'dart:isolate';
final SPAWN_PACKAGE_CONFIG = "foobar:///no/such/file/";
const String packageConfig = "foobar:///no/such/file/";
const String errorString = "IsolateSpawnException: Unable to spawn isolate:";
const String errorString2 = "Error when reading '$packageConfig'";
main([args, port]) async {
if (port != null) {
testPackageConfig(port);
return;
main([args, msg]) async {
if (msg != null) {
throw 'unreachable';
}
dynamic error;
try {
await Isolate.spawnUri(Platform.script, [], 'msg',
packageConfig: Uri.parse('foobar:///no/such/file/'));
} catch (e) {
error = e;
}
if (error == null) throw 'Expected a Spawning error.';
if (!'$error'.contains(errorString)) {
throw 'Epected: $errorString to contain "$errorString"';
}
if (!'$error'.contains(errorString2)) {
throw 'Epected: $errorString to contain "$errorString2"';
}
var p = new RawReceivePort();
Isolate.spawnUri(Platform.script, [], p.sendPort,
packageConfig: Uri.parse(SPAWN_PACKAGE_CONFIG));
p.handler = (msg) {
p.close();
if (msg[0] != SPAWN_PACKAGE_CONFIG) {
throw "Bad package config in child isolate: ${msg[0]}";
}
if (msg[1] != null) {
throw "Non-null loaded package config in isolate: ${msg[1]}";
}
print("SUCCESS");
};
print("Spawning isolate's package config: ${await Isolate.packageConfig}");
}
testPackageConfig(port) async {
var packageConfigStr = Platform.packageConfig;
var packageConfig = await Isolate.packageConfig;
print("Spawned isolate's package config flag: $packageConfigStr");
print("Spawned isolate's loaded package config: $packageConfig");
port.send([packageConfigStr, packageConfig.toString()]);
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2016, 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.
@ -8,44 +8,67 @@
import 'dart:io';
import 'dart:isolate';
final SPAWN_PACKAGE_ROOT = "file:///no/such/package/root/";
final PACKAGE_URI = "package:foo/bar.dart";
final PACKAGE_PATH = "file:///no/such/package/root/foo/bar.dart";
final packageUriToResolve = "package:foo/bar.dart";
final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
final dotPackages = """
# This is the content of a .packages file.
foo:file:///no/such/directory/lib/
""";
final packageConfigJson = """
{
"configVersion": 2,
"packages": [
{
"name": "foo",
"rootUri": "file:///no/such/directory",
"packageUri": "lib/",
"languageVersion": "2.7"
}
]
}
""";
main([args, port]) async {
if (port != null) {
testPackageResolution(port);
return;
}
var p = new RawReceivePort();
Isolate.spawnUri(Platform.script, [], p.sendPort,
packageRoot: Uri.parse(SPAWN_PACKAGE_ROOT));
p.handler = (msg) {
p.close();
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != null) {
throw "Bad package root in child isolate: ${msg[0]}";
}
if (msg[1] != null) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
};
print("Spawning isolate's package root: ${await Isolate.packageRoot}");
await runTest(dotPackages);
await runTest(packageConfigJson);
}
Future runTest(String packageConfig) async {
final data = Uri.dataFromString(packageConfig);
final port = ReceivePort();
await Isolate.spawnUri(Platform.script, [], port.sendPort,
packageConfig: data);
final msg = await port.first;
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != data.toString()) {
throw "Bad package config in child isolate: ${msg[0]}\n"
"Expected: $data";
}
if (msg[1] != packageResolvedUri) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
}
testPackageResolution(port) async {
try {
var packageRootStr = Platform.packageRoot;
var packageRoot = await Isolate.packageRoot;
var resolvedPkg = await Isolate.resolvePackageUri(Uri.parse(PACKAGE_URI));
print("Spawned isolate's package root flag: $packageRootStr");
print("Spawned isolate's loaded package root: $packageRoot");
var packageConfigStr = Platform.packageConfig;
var packageConfig = await Isolate.packageConfig;
var resolvedPkg =
await Isolate.resolvePackageUri(Uri.parse(packageUriToResolve));
print("Spawned isolate's package config flag: $packageConfigStr");
print("Spawned isolate's loaded package config: $packageConfig");
print("Spawned isolate's resolved package path: $resolvedPkg");
port.send([packageRoot.toString(), resolvedPkg.toString()]);
port.send([packageConfig?.toString(), resolvedPkg?.toString()]);
} catch (e, s) {
port.send("$e\n$s\n");
}

View file

@ -18,26 +18,30 @@ main() async {
print('TEST runWithPackagesArg = $runWithPackagesArg ');
for (final spawnWithPackageConfig in const [true, false]) {
print('TEST spawnWithPackageConfig = $spawnWithPackageConfig ');
await runDotPackagesTest(runWithPackagesArg, spawnWithPackageConfig);
final bool checkForResolveUri =
runWithPackagesArg || !spawnWithPackageConfig;
await runDotPackagesTest(
runWithPackagesArg, spawnWithPackageConfig, checkForResolveUri);
for (final optionalPackageUri in const [true, false]) {
print('TEST optionalPackageUri = $optionalPackageUri');
await runPackageConfigTest(
runWithPackagesArg, spawnWithPackageConfig, optionalPackageUri);
await runPackageConfigTest(runWithPackagesArg, spawnWithPackageConfig,
optionalPackageUri, checkForResolveUri);
}
}
}
}
Future runPackageConfigTest(
bool withPackagesArg, bool spawnWithArg, bool optionalPackageUri) async {
Future runPackageConfigTest(bool withPackagesArg, bool spawnWithArg,
bool optionalPackageUri, bool checkForResolveUri) async {
await withApplicationDirAndDotDartToolPackageConfig(
(String tempDir, String packageJson, String mainFile) async {
final args = [if (withPackagesArg) '--packages=$packageJson', mainFile];
await run(executable, args);
}, spawnWithArg, optionalPackageUri);
}, spawnWithArg, optionalPackageUri, checkForResolveUri);
}
Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async {
Future runDotPackagesTest(
bool withPackagesArg, bool spawnWithArg, bool checkForResolveUri) async {
await withApplicationDirAndDotPackages(
(String tempDir, String dotPackagesFile, String mainFile) async {
final args = [
@ -45,12 +49,13 @@ Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async {
mainFile,
];
await run(executable, args);
}, spawnWithArg);
}, spawnWithArg, checkForResolveUri);
}
Future withApplicationDirAndDotPackages(
Future fn(String tempDir, String packagesDir, String mainFile),
bool spawnWithArg) async {
bool spawnWithArg,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".packages"
final dotPackagesFile =
@ -61,8 +66,10 @@ Future withApplicationDirAndDotPackages(
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 File(mainFile).writeAsString(buildMainIsolate(
importUri,
spawnWithArg ? dotPackagesFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, dotPackagesFile, mainFile);
});
@ -71,7 +78,8 @@ Future withApplicationDirAndDotPackages(
Future withApplicationDirAndDotDartToolPackageConfig(
Future fn(String tempDir, String packageJson, String mainFile),
bool spawnWithArg,
bool optionalPackageUri) async {
bool optionalPackageUri,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".dart_tool/package_config.json"
final dotDartToolDir = path.join(tempDir, '.dart_tool');
@ -87,7 +95,9 @@ Future withApplicationDirAndDotDartToolPackageConfig(
final importUri = 'package:foo/child_isolate.dart';
await File(childIsolateFile).writeAsString(buildChildIsolate());
await File(mainFile).writeAsString(buildMainIsolate(
importUri, spawnWithArg ? packageConfigJsonFile : null));
importUri,
spawnWithArg ? packageConfigJsonFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, packageConfigJsonFile, mainFile);
});
@ -138,15 +148,22 @@ String buildChildIsolate() => '''
}
''';
String buildMainIsolate(String spawnUri, String? packageConfigUri) => '''
String buildMainIsolate(
String spawnUri, String? packageConfigUri, String? childIsolatePath) =>
'''
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 resolvedUri = await Isolate.resolvePackageUri(uri);
if ("""\${resolvedUri?.toFilePath()}""" != r"""$childIsolatePath""") {
throw 'Could not Isolate.resolvePackageUri(uri).';
}
final rp = ReceivePort();
final isolateArgs = <String>['a'];
await Isolate.spawnUri(
uri,

View file

@ -52,13 +52,6 @@ convert/utf85_test: Skip # Pass, Slow Issue 12644.
[ $arch != x64 || $compiler == dartkb || $runtime != vm ]
isolate/int32_length_overflow_test: SkipSlow
[ $compiler != none || $runtime != vm ]
isolate/package_config_test: SkipByDesign # Uses Isolate.packageConfig
isolate/package_resolve_test: SkipByDesign # Uses Isolate.resolvePackageUri
isolate/package_root_test: SkipByDesign # Uses Isolate.packageRoot
isolate/scenarios/*: SkipByDesign # Use automatic package resolution, spawnFunction and .dart URIs.
isolate/spawn_uri_fail_test: SkipByDesign # Uses dart:io.
[ $mode == product || $runtime != vm ]
isolate/checked_test: Skip # Unsupported.
@ -112,6 +105,13 @@ isolate/stacktrace_message_test: Skip # Isolate.spawnUri
isolate/static_function_test: Skip # Isolate.spawnUri
isolate/unresolved_ports_test: Skip # Isolate.spawnUri
[ $runtime != vm || $compiler != dartk && $compiler != none ]
isolate/package_config_test: SkipByDesign # Uses Isolate.packageConfig
isolate/package_resolve_test: SkipByDesign # Uses Isolate.resolvePackageUri
isolate/package_root_test: SkipByDesign # Uses Isolate.packageRoot
isolate/scenarios/*: SkipByDesign # Use automatic package resolution, spawnFunction and .dart URIs.
isolate/spawn_uri_fail_test: SkipByDesign # Uses dart:io.
[ $hot_reload || $hot_reload_rollback ]
convert/chunked_conversion_utf88_test: SkipSlow
convert/utf85_test: SkipSlow

View file

@ -8,33 +8,26 @@
import 'dart:io';
import 'dart:isolate';
final SPAWN_PACKAGE_CONFIG = "foobar:///no/such/file/";
const String packageConfig = "foobar:///no/such/file/";
const String errorString = "IsolateSpawnException: Unable to spawn isolate:";
const String errorString2 = "Error when reading '$packageConfig'";
main([args, port]) async {
if (port != null) {
testPackageConfig(port);
return;
main([args, msg]) async {
if (msg != null) {
throw 'unreachable';
}
dynamic error;
try {
await Isolate.spawnUri(Platform.script, [], 'msg',
packageConfig: Uri.parse('foobar:///no/such/file/'));
} catch (e) {
error = e;
}
if (error == null) throw 'Expected a Spawning error.';
if (!'$error'.contains(errorString)) {
throw 'Epected: $errorString to contain "$errorString"';
}
if (!'$error'.contains(errorString2)) {
throw 'Epected: $errorString to contain "$errorString2"';
}
var p = new RawReceivePort();
Isolate.spawnUri(Platform.script, [], p.sendPort,
packageConfig: Uri.parse(SPAWN_PACKAGE_CONFIG));
p.handler = (msg) {
p.close();
if (msg[0] != SPAWN_PACKAGE_CONFIG) {
throw "Bad package config in child isolate: ${msg[0]}";
}
if (msg[1] != null) {
throw "Non-null loaded package config in isolate: ${msg[1]}";
}
print("SUCCESS");
};
print("Spawning isolate's package config: ${await Isolate.packageConfig}");
}
testPackageConfig(port) async {
var packageConfigStr = Platform.packageConfig;
var packageConfig = await Isolate.packageConfig;
print("Spawned isolate's package config flag: $packageConfigStr");
print("Spawned isolate's loaded package config: $packageConfig");
port.send([packageConfigStr, packageConfig?.toString()]);
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2016, 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.
@ -8,44 +8,67 @@
import 'dart:io';
import 'dart:isolate';
final SPAWN_PACKAGE_ROOT = "file:///no/such/package/root/";
final PACKAGE_URI = "package:foo/bar.dart";
final PACKAGE_PATH = "file:///no/such/package/root/foo/bar.dart";
final packageUriToResolve = "package:foo/bar.dart";
final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
final dotPackages = """
# This is the content of a .packages file.
foo:file:///no/such/directory/lib/
""";
final packageConfigJson = """
{
"configVersion": 2,
"packages": [
{
"name": "foo",
"rootUri": "file:///no/such/directory",
"packageUri": "lib/",
"languageVersion": "2.7"
}
]
}
""";
main([args, port]) async {
if (port != null) {
testPackageResolution(port);
return;
}
var p = new RawReceivePort();
Isolate.spawnUri(Platform.script, [], p.sendPort,
packageRoot: Uri.parse(SPAWN_PACKAGE_ROOT));
p.handler = (msg) {
p.close();
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != null) {
throw "Bad package root in child isolate: ${msg[0]}";
}
if (msg[1] != null) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
};
print("Spawning isolate's package root: ${await Isolate.packageRoot}");
await runTest(dotPackages);
await runTest(packageConfigJson);
}
Future runTest(String packageConfig) async {
final data = Uri.dataFromString(packageConfig);
final port = ReceivePort();
await Isolate.spawnUri(Platform.script, [], port.sendPort,
packageConfig: data);
final msg = await port.first;
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != data.toString()) {
throw "Bad package config in child isolate: ${msg[0]}\n"
"Expected: $data";
}
if (msg[1] != packageResolvedUri) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
}
testPackageResolution(port) async {
try {
var packageRootStr = Platform.packageRoot;
var packageRoot = await Isolate.packageRoot;
var resolvedPkg = await Isolate.resolvePackageUri(Uri.parse(PACKAGE_URI));
print("Spawned isolate's package root flag: $packageRootStr");
print("Spawned isolate's loaded package root: $packageRoot");
var packageConfigStr = Platform.packageConfig;
var packageConfig = await Isolate.packageConfig;
var resolvedPkg =
await Isolate.resolvePackageUri(Uri.parse(packageUriToResolve));
print("Spawned isolate's package config flag: $packageConfigStr");
print("Spawned isolate's loaded package config: $packageConfig");
print("Spawned isolate's resolved package path: $resolvedPkg");
port.send([packageRoot?.toString(), resolvedPkg?.toString()]);
port.send([packageConfig?.toString(), resolvedPkg?.toString()]);
} catch (e, s) {
port.send("$e\n$s\n");
}

View file

@ -2,15 +2,32 @@
// 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.
// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
import 'dart:isolate';
final PACKAGE_URI = "package:foo/bar.dart";
final PACKAGE_PATH = "file:///no/such/directory/bar.dart";
final packageUriToResolve = "package:foo/bar.dart";
final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
final PACKAGE_SPEC = """
final dotPackages = """
# This is the content of a .packages file.
foo:file:///no/such/directory/
foo:file:///no/such/directory/lib/
""";
final packageConfigJson = """
{
"configVersion": 2,
"packages": [
{
"name": "foo",
"rootUri": "file:///no/such/directory",
"packageUri": "lib/",
"languageVersion": "2.7"
}
]
}
""";
main([args, port]) async {
@ -18,34 +35,36 @@ main([args, port]) async {
testPackageResolution(port);
return;
}
var data = new Uri.dataFromString(PACKAGE_SPEC);
var p = new RawReceivePort();
Isolate.spawnUri(Platform.script, [], p.sendPort, packageConfig: data);
p.handler = (msg) {
p.close();
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != data.toString()) {
throw "Bad package config in child isolate: ${msg[0]}\n"
"Expected: $data";
}
if (msg[1] != PACKAGE_PATH) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
};
print("Spawning isolate's package root: ${await Isolate.packageRoot}");
await runTest(dotPackages);
await runTest(packageConfigJson);
}
Future runTest(String packageConfig) async {
final data = Uri.dataFromString(packageConfig);
final port = ReceivePort();
await Isolate.spawnUri(Platform.script, [], port.sendPort,
packageConfig: data);
final msg = await port.first;
if (msg is! List) {
print(msg.runtimeType);
throw "Failure return from spawned isolate:\n\n$msg";
}
if (msg[0] != data.toString()) {
throw "Bad package config in child isolate: ${msg[0]}\n"
"Expected: $data";
}
if (msg[1] != packageResolvedUri) {
throw "Package path not matching: ${msg[1]}";
}
print("SUCCESS");
}
testPackageResolution(port) async {
try {
var packageRootStr = Platform.packageRoot;
var packageConfigStr = Platform.packageConfig;
var packageConfig = await Isolate.packageConfig;
var resolvedPkg = await Isolate.resolvePackageUri(Uri.parse(PACKAGE_URI));
print("Spawned isolate's package root flag: $packageRootStr");
var resolvedPkg =
await Isolate.resolvePackageUri(Uri.parse(packageUriToResolve));
print("Spawned isolate's package config flag: $packageConfigStr");
print("Spawned isolate's loaded package config: $packageConfig");
print("Spawned isolate's resolved package path: $resolvedPkg");

View file

@ -18,26 +18,30 @@ main() async {
print('TEST runWithPackagesArg = $runWithPackagesArg ');
for (final spawnWithPackageConfig in const [true, false]) {
print('TEST spawnWithPackageConfig = $spawnWithPackageConfig ');
await runDotPackagesTest(runWithPackagesArg, spawnWithPackageConfig);
final bool checkForResolveUri =
runWithPackagesArg || !spawnWithPackageConfig;
await runDotPackagesTest(
runWithPackagesArg, spawnWithPackageConfig, checkForResolveUri);
for (final optionalPackageUri in const [true, false]) {
print('TEST optionalPackageUri = $optionalPackageUri');
await runPackageConfigTest(
runWithPackagesArg, spawnWithPackageConfig, optionalPackageUri);
await runPackageConfigTest(runWithPackagesArg, spawnWithPackageConfig,
optionalPackageUri, checkForResolveUri);
}
}
}
}
Future runPackageConfigTest(
bool withPackagesArg, bool spawnWithArg, bool optionalPackageUri) async {
Future runPackageConfigTest(bool withPackagesArg, bool spawnWithArg,
bool optionalPackageUri, bool checkForResolveUri) async {
await withApplicationDirAndDotDartToolPackageConfig(
(String tempDir, String packageJson, String mainFile) async {
final args = [if (withPackagesArg) '--packages=$packageJson', mainFile];
await run(executable, args);
}, spawnWithArg, optionalPackageUri);
}, spawnWithArg, optionalPackageUri, checkForResolveUri);
}
Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async {
Future runDotPackagesTest(
bool withPackagesArg, bool spawnWithArg, bool checkForResolveUri) async {
await withApplicationDirAndDotPackages(
(String tempDir, String dotPackagesFile, String mainFile) async {
final args = [
@ -45,12 +49,13 @@ Future runDotPackagesTest(bool withPackagesArg, bool spawnWithArg) async {
mainFile,
];
await run(executable, args);
}, spawnWithArg);
}, spawnWithArg, checkForResolveUri);
}
Future withApplicationDirAndDotPackages(
Future fn(String tempDir, String packagesDir, String mainFile),
bool spawnWithArg) async {
bool spawnWithArg,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".packages"
final dotPackagesFile =
@ -61,8 +66,10 @@ Future withApplicationDirAndDotPackages(
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 File(mainFile).writeAsString(buildMainIsolate(
importUri,
spawnWithArg ? dotPackagesFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, dotPackagesFile, mainFile);
});
@ -71,7 +78,8 @@ Future withApplicationDirAndDotPackages(
Future withApplicationDirAndDotDartToolPackageConfig(
Future fn(String tempDir, String packageJson, String mainFile),
bool spawnWithArg,
bool optionalPackageUri) async {
bool optionalPackageUri,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".dart_tool/package_config.json"
final dotDartToolDir = path.join(tempDir, '.dart_tool');
@ -87,7 +95,9 @@ Future withApplicationDirAndDotDartToolPackageConfig(
final importUri = 'package:foo/child_isolate.dart';
await File(childIsolateFile).writeAsString(buildChildIsolate());
await File(mainFile).writeAsString(buildMainIsolate(
importUri, spawnWithArg ? packageConfigJsonFile : null));
importUri,
spawnWithArg ? packageConfigJsonFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, packageConfigJsonFile, mainFile);
});
@ -138,15 +148,22 @@ String buildChildIsolate() => '''
}
''';
String buildMainIsolate(String spawnUri, String packageConfigUri) => '''
String buildMainIsolate(
String spawnUri, String packageConfigUri, String childIsolatePath) =>
'''
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 resolvedUri = await Isolate.resolvePackageUri(uri);
if ("""\${resolvedUri?.toFilePath()}""" != r"""$childIsolatePath""") {
throw 'Could not Isolate.resolvePackageUri(uri).';
}
final rp = ReceivePort();
final isolateArgs = <String>['a'];
await Isolate.spawnUri(
uri,

View file

@ -52,13 +52,6 @@ convert/utf85_test: Skip # Pass, Slow Issue 12644.
[ $arch != x64 || $compiler == dartkb || $runtime != vm ]
isolate/int32_length_overflow_test: SkipSlow
[ $compiler != none || $runtime != vm ]
isolate/package_config_test: SkipByDesign # Uses Isolate.packageConfig
isolate/package_resolve_test: SkipByDesign # Uses Isolate.resolvePackageUri
isolate/package_root_test: SkipByDesign # Uses Isolate.packageRoot
isolate/scenarios/*: SkipByDesign # Use automatic package resolution, spawnFunction and .dart URIs.
isolate/spawn_uri_fail_test: SkipByDesign # Uses dart:io.
[ $mode == product || $runtime != vm ]
isolate/checked_test: Skip # Unsupported.
@ -109,6 +102,13 @@ isolate/stacktrace_message_test: Skip # Isolate.spawnUri
isolate/static_function_test: Skip # Isolate.spawnUri
isolate/unresolved_ports_test: Skip # Isolate.spawnUri
[ $runtime != vm || $compiler != dartk && $compiler != none ]
isolate/package_config_test: SkipByDesign # Uses Isolate.packageConfig
isolate/package_resolve_test: SkipByDesign # Uses Isolate.resolvePackageUri
isolate/package_root_test: SkipByDesign # Uses Isolate.packageRoot
isolate/scenarios/*: SkipByDesign # Use automatic package resolution, spawnFunction and .dart URIs.
isolate/spawn_uri_fail_test: SkipByDesign # Uses dart:io.
[ $hot_reload || $hot_reload_rollback ]
convert/chunked_conversion_utf88_test: SkipSlow
convert/utf85_test: SkipSlow