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

Side by Side Diff: runtime/bin/vmservice/loader.dart

Issue 1998963003: Rework standalone to use a synchronous loader that does not invoke Dart code (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of vmservice_io; 5 part of vmservice_io;
6 6
7 _sanitizeWindowsPath(path) {
8 // For Windows we need to massage the paths a bit according to
9 // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
10 //
11 // Convert
12 // C:\one\two\three
13 // to
14 // /C:/one/two/three
15
16 if (_isWindows == false) {
17 // Do nothing when not running Windows.
18 return path;
19 }
20
21 var fixedPath = "${path.replaceAll('\\', '/')}";
22
23 if ((path.length > 2) && (path[1] == ':')) {
24 // Path begins with a drive letter.
25 return '/$fixedPath';
26 }
27
28 return fixedPath;
29 }
30
turnidge 2016/06/03 17:50:25 extra line
Cutch 2016/06/03 22:07:32 Acknowledged.
31
32 _trimWindowsPath(path) {
33 // Convert /X:/ to X:/.
34 if (_isWindows == false) {
35 // Do nothing when not running Windows.
36 return path;
37 }
38 if (!path.startsWith('/') || (path.length < 3)) {
39 return path;
40 }
41 // Match '/?:'.
42 if ((path[0] == '/') && (path[2] == ':')) {
43 // Remove leading '/'.
44 return path.substring(1);
45 }
46 return path;
47 }
48
turnidge 2016/06/03 17:50:25 extra line - make the file consistent...
Cutch 2016/06/03 22:07:32 Done here and elsewhere.
49
50 // Ensure we have a trailing slash character.
51 _enforceTrailingSlash(uri) {
52 if (!uri.endsWith('/')) {
53 return '$uri/';
54 }
55 return uri;
56 }
57
58 // State associated with the isolate that is used for loading.
59 class IsolateLoaderState {
60 IsolateLoaderState(this.isolateId);
61
62 final int isolateId;
63
64 void init(String packageRootFlag,
65 String packagesConfigFlag,
66 String workingDirectory) {
67 // _workingDirectory must be set first.
68 _workingDirectory = new Uri.directory(workingDirectory);
69 // If the --package-root flag was passed.
70 if (packageRootFlag != null) {
71 _setPackageRoot(packageRootFlag);
72 }
73 // If the --packages flag was passed.
74 if (packagesConfigFlag != null) {
75 _setPackagesConfig(packagesConfigFlag);
76 }
77 }
78
79 // The working directory when the embedder started.
80 Uri _workingDirectory;
81
82 // The root script's uri.
83 Uri _rootScript;
84
85 bool _traceLoading = false;
86
87 // Packages are either resolved looking up in a map or resolved from within a
88 // package root.
89 bool get _packagesReady => (_packageRoot != null) ||
90 (_packageMap != null) ||
91 (_packageError != null);
92
93 // Error string set if there was an error resolving package configuration.
94 // For example not finding a .packages file or packages/ directory, malformed
95 // .packages file or any other related error.
96 String _packageError = null;
97
98 // The directory to look in to resolve "package:" scheme URIs. By default it
99 // is the 'packages' directory right next to the script.
100 Uri _packageRoot = null;
101
102 // The map describing how certain package names are mapped to Uris.
103 Uri _packageConfig = null;
104 Map<String, Uri> _packageMap = null;
105
106 _setPackageRoot(String packageRoot) {
107 packageRoot = _enforceTrailingSlash(packageRoot);
108 if (packageRoot.startsWith('file:') ||
109 packageRoot.startsWith('http:') ||
110 packageRoot.startsWith('https:')) {
111 _packageRoot = _workingDirectory.resolve(packageRoot);
112 } else {
113 packageRoot = _sanitizeWindowsPath(packageRoot);
114 packageRoot = _trimWindowsPath(packageRoot);
115 _packageRoot = _workingDirectory.resolveUri(new Uri.file(packageRoot));
116 }
117 }
118
119 _setPackagesConfig(String packagesParam) {
120 var packagesName = _sanitizeWindowsPath(packagesParam);
121 var packagesUri = Uri.parse(packagesName);
122 if (packagesUri.scheme == '') {
123 // Script does not have a scheme, assume that it is a path,
124 // resolve it against the working directory.
125 packagesUri = _workingDirectory.resolveUri(packagesUri);
126 }
127 _requestPackagesMap(packagesUri);
128 }
129
130 // Handling of access to the package root or package map from user code.
131 _triggerPackageResolution(action) {
132 if (_packagesReady) {
133 // Packages are ready. Execute the action now.
134 action();
135 } else {
136 if (_pendingPackageLoads.isEmpty) {
137 // Package resolution has not been setup yet, and this is the first
138 // request for package resolution & loading.
139 _requestPackagesMap();
140 }
141 // Register the action for when the package resolution is ready.
142 _pendingPackageLoads.add(action);
143 }
144 }
145
146 // A list of callbacks which should be invoked after the package map has been
147 // loaded.
148 List<Function> _pendingPackageLoads = [];
149
150 // Given a uri with a 'package' scheme, return a Uri that is prefixed with
151 // the package root.
152 Uri _resolvePackageUri(Uri uri) {
153 assert(uri.scheme == "package");
154 assert(_packagesReady);
155
156 if (!uri.host.isEmpty) {
157 var path = '${uri.host}${uri.path}';
158 var right = 'package:$path';
159 var wrong = 'package://$path';
160
161 throw "URIs using the 'package:' scheme should look like "
162 "'$right', not '$wrong'.";
163 }
164
165 if (_traceLoading) {
166 _log('Resolving package with uri path: ${uri.path}');
167 }
168 var resolvedUri;
169 if (_packageError != null) {
170 if (_traceLoading) {
171 _log("Resolving package with pending resolution error: $_packageError");
172 }
173 throw _packageError;
174 } else if (_packageRoot != null) {
175 resolvedUri = _packageRoot.resolve(uri.path);
176 } else {
177 var packageName = uri.pathSegments[0];
178 var mapping = _packageMap[packageName];
179 if (_traceLoading) {
180 _log("Mapped '$packageName' package to '$mapping'");
181 }
182 if (mapping == null) {
183 throw "No mapping for '$packageName' package when resolving '$uri'.";
184 }
185 var path;
186 if (uri.path.length > packageName.length) {
187 path = uri.path.substring(packageName.length + 1);
188 } else {
189 // Handle naked package resolution to the default package name:
190 // package:foo is equivalent to package:foo/foo.dart
191 assert(uri.path.length == packageName.length);
192 path = "$packageName.dart";
193 }
194 if (_traceLoading) {
195 _log("Path to be resolved in package: $path");
196 }
197 resolvedUri = mapping.resolve(path);
198 }
199 if (_traceLoading) {
200 _log("Resolved '$uri' to '$resolvedUri'.");
201 }
202 return resolvedUri;
203 }
204
205 RawReceivePort _packagesPort;
206
207 void _requestPackagesMap([Uri packageConfig]) {
208 assert(_packagesPort == null);
209 assert(_rootScript != null);
210 // Create a port to receive the packages map on.
211 _packagesPort = new RawReceivePort(_handlePackagesReply);
212 var sp = _packagesPort.sendPort;
213
214 if (packageConfig != null) {
215 // Explicitly specified .packages path.
216 _handlePackagesRequest(sp,
217 _traceLoading,
218 -2,
219 packageConfig);
220 } else {
221 // Search for .packages or packages/ starting at the root script.
222 _handlePackagesRequest(sp,
223 _traceLoading,
224 -1,
225 _rootScript);
226 }
227
228 if (_traceLoading) {
229 _log("Requested packages map for '$_rootScript'.");
230 }
231 }
232
233 void _handlePackagesReply(msg) {
234 // Make sure to close the _packagePort before any other action.
235 _packagesPort.close();
236 _packagesPort = null;
237
238 if (_traceLoading) {
239 _log("Got packages reply: $msg");
240 }
241 if (msg is String) {
242 if (_traceLoading) {
243 _log("Got failure response on package port: '$msg'");
244 }
245 // Remember the error message.
246 _packageError = msg;
247 } else if (msg is List) {
248 if (msg.length == 1) {
249 if (_traceLoading) {
250 _log("Received package root: '${msg[0]}'");
251 }
252 _packageRoot = Uri.parse(msg[0]);
253 } else {
254 // First entry contains the location of the loaded .packages file.
255 assert((msg.length % 2) == 0);
256 assert(msg.length >= 2);
257 assert(msg[1] == null);
258 _packageConfig = Uri.parse(msg[0]);
259 _packageMap = new Map<String, Uri>();
260 for (var i = 2; i < msg.length; i+=2) {
261 // TODO(iposva): Complain about duplicate entries.
262 _packageMap[msg[i]] = Uri.parse(msg[i+1]);
263 }
264 if (_traceLoading) {
265 _log("Setup package map: $_packageMap");
266 }
267 }
268 } else {
269 _packageError = "Bad type of packages reply: ${msg.runtimeType}";
270 if (_traceLoading) {
271 _log(_packageError);
272 }
273 }
274
275 // Resolve all pending package loads now that we know how to resolve them.
276 while (_pendingPackageLoads.length > 0) {
277 // Order does not matter as we queue all of the requests up right now.
278 var req = _pendingPackageLoads.removeLast();
279 // Call the registered closure, to handle the delayed action.
280 req();
281 }
282 // Reset the pending package loads to empty. So that we eventually can
283 // finish loading.
284 _pendingPackageLoads = [];
285 }
286
287 }
288
7 _log(msg) { 289 _log(msg) {
8 print("% $msg"); 290 print("% $msg");
9 } 291 }
10 292
11 var _httpClient; 293 var _httpClient;
12 294
13 // Send a response to the requesting isolate. 295 // Send a response to the requesting isolate.
14 void _sendResourceResponse(SendPort sp, int id, dynamic data) { 296 void _sendResourceResponse(SendPort sp,
297 int tag,
298 Uri uri,
299 String libraryUrl,
300 dynamic data) {
15 assert((data is List<int>) || (data is String)); 301 assert((data is List<int>) || (data is String));
16 var msg = new List(2); 302 var msg = new List(4);
17 msg[0] = id; 303 if (data is String) {
18 msg[1] = data; 304 // We encountered an error, flip the sign of the tag to indicate that.
305 tag = -tag;
306 if (libraryUrl == null) {
307 data = 'Could not load "$uri": $data';
308 } else {
309 data = 'Could not import "$uri" from "$libraryUrl": $data';
310 }
311 }
312 msg[0] = tag;
313 msg[1] = uri.toString();
314 msg[2] = libraryUrl;
315 msg[3] = data;
19 sp.send(msg); 316 sp.send(msg);
20 } 317 }
21 318
22 void _loadHttp(SendPort sp, int id, Uri uri) { 319 void _loadHttp(SendPort sp,
320 int tag,
321 Uri uri,
322 Uri resolvedUri,
323 String libraryUrl) {
23 if (_httpClient == null) { 324 if (_httpClient == null) {
24 _httpClient = new HttpClient()..maxConnectionsPerHost = 6; 325 _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
25 } 326 }
26 _httpClient.getUrl(uri) 327 _httpClient.getUrl(resolvedUri)
27 .then((HttpClientRequest request) => request.close()) 328 .then((HttpClientRequest request) => request.close())
28 .then((HttpClientResponse response) { 329 .then((HttpClientResponse response) {
29 var builder = new BytesBuilder(copy: false); 330 var builder = new BytesBuilder(copy: false);
30 response.listen( 331 response.listen(
31 builder.add, 332 builder.add,
32 onDone: () { 333 onDone: () {
33 if (response.statusCode != 200) { 334 if (response.statusCode != 200) {
34 var msg = "Failure getting $uri:\n" 335 var msg = "Failure getting $resolvedUri:\n"
35 " ${response.statusCode} ${response.reasonPhrase}"; 336 " ${response.statusCode} ${response.reasonPhrase}";
36 _sendResourceResponse(sp, id, msg); 337 _sendResourceResponse(sp, tag, uri, libraryUrl, msg);
37 } else { 338 } else {
38 _sendResourceResponse(sp, id, builder.takeBytes()); 339 _sendResourceResponse(sp, tag, uri, libraryUrl,
340 builder.takeBytes());
39 } 341 }
40 }, 342 },
41 onError: (e) { 343 onError: (e) {
42 _sendResourceResponse(sp, id, e.toString()); 344 _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
43 }); 345 });
44 }) 346 })
45 .catchError((e) { 347 .catchError((e) {
46 _sendResourceResponse(sp, id, e.toString()); 348 _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
47 }); 349 });
48 // It's just here to push an event on the event loop so that we invoke the 350 // It's just here to push an event on the event loop so that we invoke the
49 // scheduled microtasks. 351 // scheduled microtasks.
50 Timer.run(() {}); 352 Timer.run(() {});
51 } 353 }
52 354
53 void _loadFile(SendPort sp, int id, Uri uri) { 355 void _loadFile(SendPort sp,
54 var path = uri.toFilePath(); 356 int tag,
357 Uri uri,
358 Uri resolvedUri,
359 String libraryUrl) {
360 var path = resolvedUri.toFilePath();
55 var sourceFile = new File(path); 361 var sourceFile = new File(path);
56 sourceFile.readAsBytes().then((data) { 362 sourceFile.readAsBytes().then((data) {
57 _sendResourceResponse(sp, id, data); 363 _sendResourceResponse(sp, tag, uri, libraryUrl, data);
58 }, 364 },
59 onError: (e) { 365 onError: (e) {
60 _sendResourceResponse(sp, id, e.toString()); 366 _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
61 }); 367 });
62 } 368 }
63 369
64 void _loadDataUri(SendPort sp, int id, Uri uri) { 370 void _loadDataUri(SendPort sp,
371 int tag,
372 Uri uri,
373 Uri resolvedUri,
374 String libraryUrl) {
65 try { 375 try {
66 var mime = uri.data.mimeType; 376 var mime = uri.data.mimeType;
67 if ((mime != "application/dart") && 377 if ((mime != "application/dart") &&
68 (mime != "text/plain")) { 378 (mime != "text/plain")) {
69 throw "MIME-type must be application/dart or text/plain: $mime given."; 379 throw "MIME-type must be application/dart or text/plain: $mime given.";
70 } 380 }
71 var charset = uri.data.charset; 381 var charset = uri.data.charset;
72 if ((charset != "utf-8") && 382 if ((charset != "utf-8") &&
73 (charset != "US-ASCII")) { 383 (charset != "US-ASCII")) {
74 // The C++ portion of the embedder assumes UTF-8. 384 // The C++ portion of the embedder assumes UTF-8.
75 throw "Only utf-8 or US-ASCII encodings are supported: $charset given."; 385 throw "Only utf-8 or US-ASCII encodings are supported: $charset given.";
76 } 386 }
77 _sendResourceResponse(sp, id, uri.data.contentAsBytes()); 387 _sendResourceResponse(sp, tag, uri, libraryUrl, uri.data.contentAsBytes());
78 } catch (e) { 388 } catch (e) {
79 _sendResourceResponse(sp, id, "Invalid data uri ($uri):\n $e"); 389 _sendResourceResponse(sp, tag, uri, libraryUrl,
390 "Invalid data uri ($uri):\n $e");
80 } 391 }
81 } 392 }
82 393
83 _handleResourceRequest(SendPort sp, bool traceLoading, int id, Uri resource) { 394 // Loading a package URI needs to first map the package name to a loadable
84 if (resource.scheme == 'file') { 395 // URI.
85 _loadFile(sp, id, resource); 396 _loadPackage(IsolateLoaderState loaderState,
86 } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) { 397 SendPort sp,
87 _loadHttp(sp, id, resource); 398 bool traceLoading,
88 } else if ((resource.scheme == 'data')) { 399 int tag,
89 _loadDataUri(sp, id, resource); 400 Uri uri,
401 Uri resolvedUri,
402 String libraryUrl) {
403 if (loaderState._packagesReady) {
404 var resolvedUri;
405 try {
406 resolvedUri = loaderState._resolvePackageUri(uri);
407 } catch (e, s) {
408 if (traceLoading) {
409 _log("Exception ($e) when resolving package URI: $uri");
410 }
411 // Report error.
412 _sendResourceResponse(sp,
413 tag,
414 uri,
415 libraryUrl,
416 e.toString());
417 return;
418 }
419 // Recursively call with the new resolved uri.
420 _handleResourceRequest(loaderState,
421 sp,
422 traceLoading,
423 tag,
424 uri,
425 resolvedUri,
426 libraryUrl);
90 } else { 427 } else {
91 _sendResourceResponse(sp, id, 428 if (loaderState._pendingPackageLoads.isEmpty) {
92 'Unknown scheme (${resource.scheme}) for $resource'); 429 // Package resolution has not been setup yet, and this is the first
430 // request for package resolution & loading.
431 loaderState._requestPackagesMap();
432 }
433 // Register the action of loading this package once the package resolution
434 // is ready.
435 loaderState._pendingPackageLoads.add(() {
436 _handleResourceRequest(loaderState,
437 sp,
438 traceLoading,
439 tag,
440 uri,
441 uri,
442 libraryUrl);
443 });
444 if (traceLoading) {
445 _log("Pending package load of '$uri': "
446 "${loaderState._pendingPackageLoads.length} pending");
447 }
93 } 448 }
94 } 449 }
95 450
451 // TODO(johnmccutchan): This and most other top level functions in this file
452 // should be turned into methods on the IsolateLoaderState class.
453 _handleResourceRequest(IsolateLoaderState loaderState,
454 SendPort sp,
455 bool traceLoading,
456 int tag,
457 Uri uri,
458 Uri resolvedUri,
459 String libraryUrl) {
460 if (resolvedUri.scheme == 'file') {
461 _loadFile(sp, tag, uri, resolvedUri, libraryUrl);
462 } else if ((resolvedUri.scheme == 'http') ||
463 (resolvedUri.scheme == 'https')) {
464 _loadHttp(sp, tag, uri, resolvedUri, libraryUrl);
465 } else if ((resolvedUri.scheme == 'data')) {
466 _loadDataUri(sp, tag, uri, resolvedUri, libraryUrl);
467 } else if ((resolvedUri.scheme == 'package')) {
468 _loadPackage(loaderState,
469 sp,
470 traceLoading,
471 tag,
472 uri,
473 resolvedUri,
474 libraryUrl);
475 } else {
476 _sendResourceResponse(sp, tag,
477 uri,
478 libraryUrl,
479 'Unknown scheme (${resolvedUri.scheme}) for '
480 '$resolvedUri');
481 }
482 }
483
96 484
97 // Handling of packages requests. Finding and parsing of .packages file or 485 // Handling of packages requests. Finding and parsing of .packages file or
98 // packages/ directories. 486 // packages/ directories.
99 const _LF = 0x0A; 487 const _LF = 0x0A;
100 const _CR = 0x0D; 488 const _CR = 0x0D;
101 const _SPACE = 0x20; 489 const _SPACE = 0x20;
102 const _HASH = 0x23; 490 const _HASH = 0x23;
103 const _DOT = 0x2E; 491 const _DOT = 0x2E;
104 const _COLON = 0x3A; 492 const _COLON = 0x3A;
105 const _DEL = 0x7F; 493 const _DEL = 0x7F;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 } 770 }
383 _parsePackagesFile(sp, traceLoading, resource, data.contentAsBytes()); 771 _parsePackagesFile(sp, traceLoading, resource, data.contentAsBytes());
384 } catch (e) { 772 } catch (e) {
385 sp.send("Uncaught error ($e) loading packages data."); 773 sp.send("Uncaught error ($e) loading packages data.");
386 } 774 }
387 } 775 }
388 776
389 777
390 _handlePackagesRequest(SendPort sp, 778 _handlePackagesRequest(SendPort sp,
391 bool traceLoading, 779 bool traceLoading,
392 int id, 780 int tag,
393 Uri resource) async { 781 Uri resource) async {
394 try { 782 try {
395 if (id == -1) { 783 if (tag == -1) {
396 if (resource.scheme == 'file') { 784 if (resource.scheme == 'file') {
397 _findPackagesFile(sp, traceLoading, resource); 785 _findPackagesFile(sp, traceLoading, resource);
398 } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) { 786 } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
399 // Try to load the .packages file next to the resource. 787 // Try to load the .packages file next to the resource.
400 var packagesUri = resource.resolve(".packages"); 788 var packagesUri = resource.resolve(".packages");
401 var exists = await _loadHttpPackagesFile(sp, traceLoading, packagesUri); 789 var exists = await _loadHttpPackagesFile(sp, traceLoading, packagesUri);
402 if (!exists) { 790 if (!exists) {
403 // If the loading of the .packages file failed for http/https based 791 // If the loading of the .packages file failed for http/https based
404 // scripts then setup the package root. 792 // scripts then setup the package root.
405 var packageRoot = resource.resolve('packages/'); 793 var packageRoot = resource.resolve('packages/');
406 sp.send([packageRoot.toString()]); 794 sp.send([packageRoot.toString()]);
407 } 795 }
408 } else { 796 } else {
409 sp.send("Unsupported scheme used to locate .packages file: " 797 sp.send("Unsupported scheme used to locate .packages file: "
410 "'$resource'."); 798 "'$resource'.");
411 } 799 }
412 } else if (id == -2) { 800 } else if (tag == -2) {
413 if (traceLoading) { 801 if (traceLoading) {
414 _log("Handling load of packages map: '$resource'."); 802 _log("Handling load of packages map: '$resource'.");
415 } 803 }
416 if (resource.scheme == 'file') { 804 if (resource.scheme == 'file') {
417 var exists = await new File.fromUri(resource).exists(); 805 var exists = await new File.fromUri(resource).exists();
418 if (exists) { 806 if (exists) {
419 _loadPackagesFile(sp, traceLoading, resource); 807 _loadPackagesFile(sp, traceLoading, resource);
420 } else { 808 } else {
421 sp.send("Packages file '$resource' not found."); 809 sp.send("Packages file '$resource' not found.");
422 } 810 }
423 } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) { 811 } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
424 var exists = await _loadHttpPackagesFile(sp, traceLoading, resource); 812 var exists = await _loadHttpPackagesFile(sp, traceLoading, resource);
425 if (!exists) { 813 if (!exists) {
426 sp.send("Packages file '$resource' not found."); 814 sp.send("Packages file '$resource' not found.");
427 } 815 }
428 } else if (resource.scheme == 'data') { 816 } else if (resource.scheme == 'data') {
429 _loadPackagesData(sp, traceLoading, resource); 817 _loadPackagesData(sp, traceLoading, resource);
430 } else { 818 } else {
431 sp.send("Unknown scheme (${resource.scheme}) for package file at " 819 sp.send("Unknown scheme (${resource.scheme}) for package file at "
432 "'$resource'."); 820 "'$resource'.");
433 } 821 }
434 } else { 822 } else {
435 sp.send("Unknown packages request id: $id for '$resource'."); 823 sp.send("Unknown packages request tag: $tag for '$resource'.");
turnidge 2016/06/03 17:50:25 Might be worth a comment that this sendport is now
Cutch 2016/06/03 22:07:32 Done.
436 } 824 }
437 } catch (e, s) { 825 } catch (e, s) {
438 if (traceLoading) { 826 if (traceLoading) {
439 _log("Error handling packages request: $e\n$s"); 827 _log("Error handling packages request: $e\n$s");
440 } 828 }
441 sp.send("Uncaught error ($e) handling packages request."); 829 sp.send("Uncaught error ($e) handling packages request.");
442 } 830 }
443 } 831 }
444 832
833 final Map<int, IsolateLoaderState> _isolateLoaders =
834 new Map<int, IsolateLoaderState>();
835
836 // See Dart_LibraryTag in dart_api.h
837 const _Dart_kCanonicalizeUrl = 0; // Canonicalize the URL.
838 const _Dart_kScriptTag = 1; // Load the root script.
839 const _Dart_kSourceTag = 2; // Load a part source.
840 const _Dart_kImportTag = 3; // Import a library.
841
842 // Extra requests. Keep these in sync between loader.dart and builtin.dart.
843 const _Dart_kInitLoader = 4; // Initialize the loader.
844 const _Dart_kResourceLoad = 5; // Resource class support.
845 const _Dart_kGetPackageRootUri = 6; // Uri of the packages/ directory.
846 const _Dart_kGetPackageConfigUri = 7; // Uri of the .packages file.
847 const _Dart_kResolvePackageUri = 8; // Resolve a package: uri.
445 848
446 // External entry point for loader requests. 849 // External entry point for loader requests.
447 _processLoadRequest(request) { 850 _processLoadRequest(request) {
448 SendPort sp = request[0]; 851 assert(request is List);
449 assert(sp != null); 852 assert(request.length > 4);
450 bool traceLoading = request[1]; 853
451 assert(traceLoading != null); 854 // Should we trace loading?
452 int id = request[2]; 855 bool traceLoading = request[0];
453 assert(id != null); 856
454 String resource = request[3]; 857 // This is the sending isolate's Dart_GetMainPortId().
455 assert(resource != null); 858 int isolateId = request[1];
456 var uri = Uri.parse(resource); 859
457 if (id >= 0) { 860 // The tag describing the operation.
458 _handleResourceRequest(sp, traceLoading, id, uri); 861 int tag = request[2];
459 } else { 862
460 _handlePackagesRequest(sp, traceLoading, id, uri); 863 // The send port to send the response on.
864 SendPort sp = request[3];
865
866 // Grab the loader state for the requesting isolate.
867 IsolateLoaderState loaderState = _isolateLoaders[isolateId];
868
869 // We are either about to initialize the loader, or, we already have.
870 assert((tag == _Dart_kInitLoader) || (loaderState != null));
871
872 // Handle the request specified in the tag.
873 switch (tag) {
874 case _Dart_kScriptTag: {
875 Uri uri = Uri.parse(request[4]);
876 // Remember the root script.
877 loaderState._rootScript = uri;
878 _handleResourceRequest(loaderState,
879 sp,
880 traceLoading,
881 tag,
882 uri,
883 uri,
884 null);
885 }
886 break;
887 case _Dart_kSourceTag:
888 case _Dart_kImportTag: {
889 // The url of the file being loaded.
890 var uri = Uri.parse(request[4]);
891 // The library that is importing/parting the file.
892 String libraryUrl = request[5];
893 _handleResourceRequest(loaderState,
894 sp,
895 traceLoading,
896 tag,
897 uri,
898 uri,
899 libraryUrl);
900 }
901 break;
902 case _Dart_kInitLoader: {
903 String packageRoot = request[4];
904 String packagesFile = request[5];
905 String workingDirectory = request[6];
906 if (loaderState == null) {
907 loaderState = new IsolateLoaderState(isolateId);
908 _isolateLoaders[isolateId] = loaderState;
909 }
910 loaderState.init(packageRoot, packagesFile, workingDirectory);
911 assert(_isolateLoaders[isolateId] == loaderState);
912 }
913 break;
914 case _Dart_kResourceLoad: {
915 Uri uri = Uri.parse(request[4]);
916 _handleResourceRequest(loaderState,
917 sp,
918 traceLoading,
919 tag,
920 uri,
921 uri,
922 null);
923 }
924 break;
925 case _Dart_kGetPackageRootUri:
926 loaderState._triggerPackageResolution(() {
927 // Respond with the package root (if any) after package resolution.
928 sp.send(loaderState._packageRoot);
929 });
930 break;
931 case _Dart_kGetPackageConfigUri:
932 loaderState._triggerPackageResolution(() {
933 // Respond with the packages config (if any) after package resolution.
934 sp.send(loaderState._packageConfig);
935 });
936 break;
937 case _Dart_kResolvePackageUri:
938 Uri uri = Uri.parse(request[4]);
939 loaderState._triggerPackageResolution(() {
940 // Respond with the resolved package uri after package resolution.
941 Uri resolvedUri;
942 try {
943 resolvedUri = loaderState._resolvePackageUri(uri);
944 } catch (e, s) {
945 if (traceLoading) {
946 _log("Exception ($e) when resolving package URI: $uri");
947 }
948 resolvedUri = null;
949 }
950 sp.send(resolvedUri);
951 });
952 break;
953 default:
954 _log('Unknown loader request tag=$tag from $isolateId');
461 } 955 }
462 } 956 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698