Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2956)

Unified Diff: runtime/bin/vmservice/loader.dart

Issue 1232593003: - Implement .packages specification. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Walkup the directory hierarchy. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/bin/vmservice/loader.dart
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index a95df089b91bb5319f2b9687e8cf8cf951d68653..4fafa00ed1657b6b1bf7386cac4fa754de120f84 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -4,10 +4,14 @@
part of vmservice_io;
+_log(msg) {
+ print("% $msg");
+}
+
var _httpClient;
// Send a response to the requesting isolate.
-void _sendResponse(SendPort sp, int id, dynamic data) {
+void _sendResourceResponse(SendPort sp, int id, dynamic data) {
assert((data is List<int>) || (data is String));
var msg = new List(2);
msg[0] = id;
@@ -29,17 +33,17 @@ void _loadHttp(SendPort sp, int id, Uri uri) {
if (response.statusCode != 200) {
var msg = "Failure getting $uri:\n"
" ${response.statusCode} ${response.reasonPhrase}";
- _sendResponse(sp, id, msg);
+ _sendResourceResponse(sp, id, msg);
} else {
- _sendResponse(sp, id, builder.takeBytes());
+ _sendResourceResponse(sp, id, builder.takeBytes());
}
},
onError: (e) {
- _sendResponse(sp, d, e.toString());
+ _sendResourceResponse(sp, id, e.toString());
});
})
.catchError((e) {
- _sendResponse(sp, id, e.toString());
+ _sendResourceResponse(sp, id, e.toString());
});
// It's just here to push an event on the event loop so that we invoke the
// scheduled microtasks.
@@ -50,11 +54,11 @@ void _loadFile(SendPort sp, int id, Uri uri) {
var path = uri.toFilePath();
var sourceFile = new File(path);
sourceFile.readAsBytes().then((data) {
- _sendResponse(sp, id, data);
+ _sendResourceResponse(sp, id, data);
},
onError: (e) {
var err = "Error loading $uri:\n $e";
- _sendResponse(sp, id, err);
+ _sendResourceResponse(sp, id, err);
});
}
@@ -83,24 +87,303 @@ void _loadDataUri(SendPort sp, int id, Uri uri) {
}
var data = UTF8.encode(Uri.decodeComponent(encodedData));
- _sendResponse(sp, id, data);
+ _sendResourceResponse(sp, id, data);
} catch (e) {
- _sendResponse(sp, id, "Invalid data uri ($uri):\n $e");
+ _sendResourceResponse(sp, id, "Invalid data uri ($uri):\n $e");
+ }
+}
+
+_handleResourceRequest(SendPort sp, bool traceLoading, int id, Uri resource) {
+ if (resource.scheme == 'file') {
+ _loadFile(sp, id, resource);
+ } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
+ _loadHttp(sp, id, resource);
+ } else if ((resource.scheme == 'data')) {
+ _loadDataUri(sp, id, resource);
+ } else {
+ _sendResourceResponse(sp, id,
+ 'Unknown scheme (${resource.scheme}) for $resource');
}
}
+
+// 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;
+
+const _invalidPackageNameChars = const [
+ // space ! " # $ % & '
+ true , false, true , true , false, true , false, false,
+ // ( ) * + , - . /
+ false, false, false, false, false, false, false, true ,
+ // 0 1 2 3 4 5 6 7
+ false, false, false, false, false, false, false, false,
+ // 8 9 : ; < = > ?
+ false, false, true , false, true , false, true , true ,
+ // @ A B C D E F G
+ false, false, false, false, false, false, false, false,
+ // H I J K L M N O
+ false, false, false, false, false, false, false, false,
+ // P Q R S T U V W
+ false, false, false, false, false, false, false, false,
+ // X Y Z [ \ ] ^ _
+ false, false, false, true , true , true , true , false,
+ // ` a b c d e f g
+ true , false, false, false, false, false, false, false,
+ // h i j k l m n o
+ false, false, false, false, false, false, false, false,
+ // p q r s t u v w
+ false, false, false, false, false, false, false, false,
+ // x y z { | } ~ DEL
+ false, false, false, true , true , true , false, true
+];
+
+_parsePackagesFile(SendPort sp,
+ bool traceLoading,
+ Uri packagesFile,
+ List<int> data) {
+ var result = [];
+ 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++;
+ 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 (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];
+ }
+ } else if ((char == _CR) || (char == _LF)) {
+ // Identify end of line.
+ 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");
+ }
+ sp.send("Missing package name in $packagesFile:\n"
+ "$line");
+ return;
+ }
+
+ // 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");
+ }
+ sp.send("Missing ':' separator in $packagesFile:\n"
+ "$line");
+ return;
+ }
+
+ var packageName = new String.fromCharCodes(data, start, separator);
siva 2015/07/28 23:50:09 packageName duplicate check (needs to be a warning
Ivan Posva 2015/07/29 18:22:18 Added TODO in builtin.dart where we are adding the
+
+ // 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");
+ }
+ sp.send("Invalid package name '$packageName' in $packagesFile:\n"
+ "$line");
+ return;
+ }
+
+ if (traceLoading) {
+ _log("packageName: $packageName");
+ }
+ var packageUri = new String.fromCharCodes(data, separator + 1, end);
+ if (traceLoading) {
+ _log("original packageUri: $packageUri");
+ }
+ // Ensure the package uri ends with a /.
+ if (!packageUri.endsWith("/")) {
+ packageUri = "$packageUri/";
+ }
+ packageUri = packagesFile.resolve(packageUri).toString();
+ if (traceLoading) {
+ _log("mapping: $packageName -> $packageUri");
+ }
+ result.add(packageName);
+ result.add(packageUri);
+ }
+
+ if (traceLoading) {
+ _log("Parsed packages file at $packagesFile. Sending:\n$result");
+ }
+ sp.send(result);
+}
+
+_loadPackagesFile(SendPort sp, bool traceLoading, Uri packagesFile) async {
+ try {
+ var data = await new File.fromUri(packagesFile).readAsBytes();
+ if (traceLoading) {
+ _log("Loaded packages file from $packagesFile:\n"
+ "${new String.fromCharCodes(data)}");
+ }
+ _parsePackagesFile(sp, traceLoading, packagesFile, data);
+ } catch (e, s) {
+ if (traceLoading) {
+ _log("Error loading packages: $e\n$s");
+ }
+ sp.send("Uncaught error ($e) loading packags file.");
+ }
+}
+
+_findPackagesFile(SendPort sp, bool traceLoading, Uri base) async {
+ try {
+ // Check for the existence of a .packages file and if it exists try to load
+ // and parse it.
+ var packagesFile = base.resolve(".packages");
+ if (traceLoading) {
+ _log("Checking for $packagesFile file.");
+ }
+ var exists = await new File.fromUri(packagesFile).exists();
+ if (traceLoading) {
+ _log("$packagesFile exists: $exists");
+ }
+ if (exists) {
+ _loadPackagesFile(sp, traceLoading, packagesFile);
+ return;
+ }
+
+ // Try whether there is a packages/ directory instead.
+ var packageRoot = base.resolve("packages/");
+ if (traceLoading) {
+ _log("Checking for $packageRoot directory.");
+ }
+ exists = await new Directory.fromUri(packageRoot).exists();
+ if (traceLoading) {
+ _log("$packageRoot exists: $exists");
+ }
+ if (exists) {
+ if (traceLoading) {
+ _log("Found a package root at: $packageRoot");
+ }
+ sp.send([packageRoot.toString()]);
+ return;
+ }
+
+ // Walk up the directory hierarchy to check for the existence of
+ // .packages files in parent directories.
+ var dir = new File.fromUri(base).parent;
+ var parent = dir.parent;
+ // Keep searching until we reach the root.
+ while (parent.path != dir.path) {
+ // Already looked in dir: Move up one level.
+ dir = parent;
+ parent = dir.parent;
+ packagesFile = dir.uri.resolve(".packages");
+ if (traceLoading) {
+ _log("Checking for $packagesFile file.");
+ }
+ exists = await new File.fromUri(packagesFile).exists();
+ if (traceLoading) {
+ _log("$packagesFile exists: $exists");
+ }
+ if (exists) {
+ _loadPackagesFile(sp, traceLoading, packagesFile);
+ return;
+ }
siva 2015/07/28 23:50:09 This chunk of code for finiding ".packages" file c
Ivan Posva 2015/07/29 18:22:18 Refactored into a single loop. It probably now mak
+ }
+
+ // No .packages file was found.
+ if (traceLoading) {
+ _log("Could not resolve a package location from $base");
+ }
+ sp.send("Could not resolve a package location for base at $base");
+ } catch (e, s) {
+ if (traceLoading) {
+ _log("Error loading packages: $e\n$s");
+ }
+ sp.send("Uncaught error ($e) loading packages file.");
+ }
+}
+
+_handlePackagesRequest(SendPort sp, bool traceLoading, int id, Uri resource) {
+ if (id == -1) {
siva 2015/07/28 23:50:09 -1 and -2 seem like magic numbers maybe we can hav
+ if (resource.scheme == 'file') {
+ _findPackagesFile(sp, traceLoading, resource);
+ } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
+ // TODO(iposva): Check for the existence of a .packages file when loading
+ // from http or https.
+ var packageRoot = resource.resolve('packages/');
+ sp.send([packageRoot.toString()]);
+ } else {
+ sp.send("Unsupported base URI to identify .packages file: '$resource'.");
+ }
+ } else if (id == -2) {
+ if (traceLoading) {
+ _log("Handling load of packages map: '$resource'.");
+ }
+ _loadPackagesFile(sp, traceLoading, resource);
+ } else {
+ sp.send("Unknown packages request id: $id for '$resource'.");
+ }
+}
+
+
+// External entry point for loader requests.
_processLoadRequest(request) {
SendPort sp = request[0];
- int id = request[1];
- String resource = request[2];
- var uri = Uri.parse(request[2]);
- if (uri.scheme == 'file') {
- _loadFile(sp, id, uri);
- } else if ((uri.scheme == 'http') || (uri.scheme == 'https')) {
- _loadHttp(sp, id, uri);
- } else if ((uri.scheme == 'data')) {
- _loadDataUri(sp, id, uri);
+ assert(sp != null);
+ bool traceLoading = request[1];
+ assert(traceLoading != null);
+ int id = request[2];
+ assert(id != null);
+ String resource = request[3];
+ assert(resource != null);
+ var uri = Uri.parse(resource);
+ if (id >= 0) {
+ _handleResourceRequest(sp, traceLoading, id, uri);
} else {
- sp.send([id, 'Unknown scheme (${uri.scheme}) for $uri']);
+ _handlePackagesRequest(sp, traceLoading, id, uri);
}
}
« runtime/bin/main.cc ('K') | « runtime/bin/main.cc ('k') | runtime/bin/vmservice_dartium.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698