OLD | NEW |
---|---|
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 Loading... | |
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 } |
OLD | NEW |