| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 library builtin; | 5 library builtin; |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 // import 'root_library'; happens here from C Code | 9 // import 'root_library'; happens here from C Code |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 _Logger._printString(msg); | 34 _Logger._printString(msg); |
| 35 } | 35 } |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 // Corelib 'Uri.base' implementation. | 39 // Corelib 'Uri.base' implementation. |
| 40 Uri _uriBase() { | 40 Uri _uriBase() { |
| 41 return new Uri.file(Directory.current.path + "/"); | 41 return new Uri.file(Directory.current.path + "/"); |
| 42 } | 42 } |
| 43 | 43 |
| 44 |
| 44 _getUriBaseClosure() => _uriBase; | 45 _getUriBaseClosure() => _uriBase; |
| 45 | 46 |
| 46 | 47 |
| 47 var _httpRequestResponseCode = 0; | |
| 48 var _httpRequestStatusString; | |
| 49 var _httpRequestResponse; | |
| 50 | |
| 51 _getHttpRequestResponseCode() => _httpRequestResponseCode; | |
| 52 _getHttpRequestStatusString() => _httpRequestStatusString; | |
| 53 _getHttpRequestResponse() => _httpRequestResponse; | |
| 54 | |
| 55 void _requestCompleted(List<int> data, HttpClientResponse response) { | |
| 56 _httpRequestResponseCode = response.statusCode; | |
| 57 _httpRequestStatusString = '${response.statusCode} ${response.reasonPhrase}'; | |
| 58 _httpRequestResponse = null; | |
| 59 if (response.statusCode != 200 || | |
| 60 (response.headers.contentType != null && | |
| 61 response.headers.contentType.mimeType == 'application/json')) { | |
| 62 return; | |
| 63 } | |
| 64 _httpRequestResponse = data; | |
| 65 } | |
| 66 | |
| 67 | |
| 68 void _requestFailed(error) { | |
| 69 _httpRequestResponseCode = 0; | |
| 70 _httpRequestStatusString = error.toString(); | |
| 71 _httpRequestResponse = null; | |
| 72 } | |
| 73 | |
| 74 | |
| 75 void _makeHttpRequest(String uri) { | |
| 76 var _client = new HttpClient(); | |
| 77 _httpRequestResponseCode = 0; | |
| 78 _httpRequestStatusString = null; | |
| 79 _httpRequestResponse = null; | |
| 80 try { | |
| 81 Uri requestUri = Uri.parse(uri); | |
| 82 _client.getUrl(requestUri) | |
| 83 .then((HttpClientRequest request) { | |
| 84 request.persistentConnection = false; | |
| 85 return request.close(); | |
| 86 }) | |
| 87 .then((HttpClientResponse response) { | |
| 88 // Only create a ByteBuilder, if multiple chunks are received. | |
| 89 var builder = new BytesBuilder(copy: false); | |
| 90 response.listen( | |
| 91 builder.add, | |
| 92 onDone: () { | |
| 93 _requestCompleted(builder.takeBytes(), response); | |
| 94 // Close the client to stop any timers currently held alive. | |
| 95 _client.close(); | |
| 96 }, | |
| 97 onError: _requestFailed); | |
| 98 }).catchError((error) { | |
| 99 _requestFailed(error); | |
| 100 }); | |
| 101 } catch (error) { | |
| 102 _requestFailed(error); | |
| 103 } | |
| 104 // TODO(floitsch): remove this line. It's just here to push an event on the | |
| 105 // event loop so that we invoke the scheduled microtasks. Also remove the | |
| 106 // import of dart:async when this line is not needed anymore. | |
| 107 Timer.run(() {}); | |
| 108 } | |
| 109 | |
| 110 | |
| 111 void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) { | |
| 112 var httpClient = new HttpClient(); | |
| 113 try { | |
| 114 httpClient.getUrl(uri) | |
| 115 .then((HttpClientRequest request) { | |
| 116 request.persistentConnection = false; | |
| 117 return request.close(); | |
| 118 }) | |
| 119 .then((HttpClientResponse response) { | |
| 120 // Only create a ByteBuilder if multiple chunks are received. | |
| 121 var builder = new BytesBuilder(copy: false); | |
| 122 response.listen( | |
| 123 builder.add, | |
| 124 onDone: () { | |
| 125 if (response.statusCode != 200) { | |
| 126 var msg = 'Failure getting $uri: ' | |
| 127 '${response.statusCode} ${response.reasonPhrase}'; | |
| 128 _asyncLoadError(uri.toString(), libraryUri, msg); | |
| 129 } | |
| 130 | |
| 131 List<int> data = builder.takeBytes(); | |
| 132 httpClient.close(); | |
| 133 loadCallback(data); | |
| 134 }, | |
| 135 onError: (error) { | |
| 136 _asyncLoadError(uri.toString(), libraryUri, error); | |
| 137 }); | |
| 138 }) | |
| 139 .catchError((error) { | |
| 140 _asyncLoadError(uri.toString(), libraryUri, error); | |
| 141 }); | |
| 142 } catch (error) { | |
| 143 _asyncLoadError(uri.toString(), libraryUri, error); | |
| 144 } | |
| 145 // TODO(floitsch): remove this line. It's just here to push an event on the | |
| 146 // event loop so that we invoke the scheduled microtasks. Also remove the | |
| 147 // import of dart:async when this line is not needed anymore. | |
| 148 Timer.run(() {}); | |
| 149 } | |
| 150 | |
| 151 | |
| 152 // Are we running on Windows? | 48 // Are we running on Windows? |
| 153 var _isWindows = false; | 49 var _isWindows = false; |
| 154 var _workingWindowsDrivePrefix; | 50 var _workingWindowsDrivePrefix; |
| 155 // The current working directory | 51 // The current working directory |
| 156 var _workingDirectoryUri; | 52 var _workingDirectoryUri; |
| 157 // The URI that the entry point script was loaded from. Remembered so that | 53 // The URI that the entry point script was loaded from. Remembered so that |
| 158 // package imports can be resolved relative to it. | 54 // package imports can be resolved relative to it. |
| 159 var _entryPointScript; | 55 var _entryPointScript; |
| 160 // The directory to look in to resolve "package:" scheme URIs. | 56 // The directory to look in to resolve "package:" scheme URIs. |
| 161 var _packageRoot; | 57 var _packageRoot; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 | 199 |
| 304 var packageRoot = _packageRoot == null ? | 200 var packageRoot = _packageRoot == null ? |
| 305 _entryPointScript.resolve('packages/') : | 201 _entryPointScript.resolve('packages/') : |
| 306 _packageRoot; | 202 _packageRoot; |
| 307 return _filePathFromUri(packageRoot.resolve(uri.path).toString()); | 203 return _filePathFromUri(packageRoot.resolve(uri.path).toString()); |
| 308 } | 204 } |
| 309 | 205 |
| 310 | 206 |
| 311 int _numOutstandingLoadRequests = 0; | 207 int _numOutstandingLoadRequests = 0; |
| 312 | 208 |
| 209 |
| 210 void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) { |
| 211 var httpClient = new HttpClient(); |
| 212 try { |
| 213 httpClient.getUrl(uri) |
| 214 .then((HttpClientRequest request) { |
| 215 request.persistentConnection = false; |
| 216 return request.close(); |
| 217 }) |
| 218 .then((HttpClientResponse response) { |
| 219 // Only create a ByteBuilder if multiple chunks are received. |
| 220 var builder = new BytesBuilder(copy: false); |
| 221 response.listen( |
| 222 builder.add, |
| 223 onDone: () { |
| 224 if (response.statusCode != 200) { |
| 225 var msg = 'Failure getting $uri: ' |
| 226 '${response.statusCode} ${response.reasonPhrase}'; |
| 227 _asyncLoadError(uri.toString(), libraryUri, msg); |
| 228 } |
| 229 |
| 230 List<int> data = builder.takeBytes(); |
| 231 httpClient.close(); |
| 232 loadCallback(data); |
| 233 }, |
| 234 onError: (error) { |
| 235 _asyncLoadError(uri.toString(), libraryUri, error); |
| 236 }); |
| 237 }) |
| 238 .catchError((error) { |
| 239 _asyncLoadError(uri.toString(), libraryUri, error); |
| 240 }); |
| 241 } catch (error) { |
| 242 _asyncLoadError(uri.toString(), libraryUri, error); |
| 243 } |
| 244 // TODO(floitsch): remove this line. It's just here to push an event on the |
| 245 // event loop so that we invoke the scheduled microtasks. Also remove the |
| 246 // import of dart:async when this line is not needed anymore. |
| 247 Timer.run(() {}); |
| 248 } |
| 249 |
| 250 |
| 313 void _signalDoneLoading() native "Builtin_DoneLoading"; | 251 void _signalDoneLoading() native "Builtin_DoneLoading"; |
| 314 | 252 |
| 315 void _loadScriptCallback(String uri, List<int> data) native "Builtin_LoadScript"
; | 253 void _loadScriptCallback(int tag, String uri, String libraryUri, List<int> data) |
| 254 native "Builtin_LoadScript"; |
| 316 | 255 |
| 317 void _loadScript(String uri, List<int> data) { | 256 void _loadScript(int tag, String uri, String libraryUri, List<int> data) { |
| 318 // TODO: Currently a compilation error while loading the script is | 257 // TODO: Currently a compilation error while loading the script is |
| 319 // fatal for the isolate. _loadScriptCallback() does not return and | 258 // fatal for the isolate. _loadScriptCallback() does not return and |
| 320 // the _numOutstandingLoadRequests counter remains out of sync. | 259 // the _numOutstandingLoadRequests counter remains out of sync. |
| 321 _loadScriptCallback(uri, data); | 260 _loadScriptCallback(tag, uri, libraryUri, data); |
| 322 assert(_numOutstandingLoadRequests > 0); | 261 assert(_numOutstandingLoadRequests > 0); |
| 323 _numOutstandingLoadRequests--; | 262 _numOutstandingLoadRequests--; |
| 324 _logResolution("native Builtin_LoadScript($uri) completed, " | 263 _logResolution("native Builtin_LoadScript($uri) completed, " |
| 325 "${_numOutstandingLoadRequests} requests remaining"); | 264 "${_numOutstandingLoadRequests} requests remaining"); |
| 326 if (_numOutstandingLoadRequests == 0) { | 265 if (_numOutstandingLoadRequests == 0) { |
| 327 _signalDoneLoading(); | 266 _signalDoneLoading(); |
| 328 } | 267 } |
| 329 } | 268 } |
| 330 | 269 |
| 331 | 270 |
| 332 void _asyncLoadErrorCallback(uri, libraryUri, error) | 271 void _asyncLoadErrorCallback(uri, libraryUri, error) |
| 333 native "Builtin_AsyncLoadError"; | 272 native "Builtin_AsyncLoadError"; |
| 334 | 273 |
| 335 void _asyncLoadError(uri, libraryUri, error) { | 274 void _asyncLoadError(uri, libraryUri, error) { |
| 336 assert(_numOutstandingLoadRequests > 0); | 275 assert(_numOutstandingLoadRequests > 0); |
| 337 _logResolution("_asyncLoadError($uri), error: $error"); | 276 _logResolution("_asyncLoadError($uri), error: $error"); |
| 338 _numOutstandingLoadRequests--; | 277 _numOutstandingLoadRequests--; |
| 339 _asyncLoadErrorCallback(uri, libraryUri, error); | 278 _asyncLoadErrorCallback(uri, libraryUri, error); |
| 340 if (_numOutstandingLoadRequests == 0) { | 279 if (_numOutstandingLoadRequests == 0) { |
| 341 _signalDoneLoading(); | 280 _signalDoneLoading(); |
| 342 } | 281 } |
| 343 } | 282 } |
| 344 | 283 |
| 345 | 284 |
| 346 // Asynchronously loads script data (source or snapshot) through | 285 // Asynchronously loads script data through a http or file uri. |
| 347 // an http or file uri. | 286 _loadDataAsync(int tag, String uri, String libraryUri) { |
| 348 _loadDataAsync(String uri) { | 287 var filePath = _filePathFromUri(uri); |
| 349 uri = _resolveScriptUri(uri); | 288 Uri sourceUri; |
| 350 Uri sourceUri = Uri.parse(uri); | 289 if (tag == null) { |
| 290 uri = _resolveScriptUri(uri); |
| 291 sourceUri = Uri.parse(uri); |
| 292 } else { |
| 293 sourceUri = Uri.parse(filePath); |
| 294 } |
| 351 _numOutstandingLoadRequests++; | 295 _numOutstandingLoadRequests++; |
| 352 _logResolution("_loadDataAsync($uri), " | 296 _logResolution("_loadDataAsync($uri), " |
| 353 "${_numOutstandingLoadRequests} requests outstanding"); | 297 "${_numOutstandingLoadRequests} requests outstanding"); |
| 354 if (sourceUri.scheme == 'http') { | 298 if (sourceUri.scheme == 'http') { |
| 355 _httpGet(sourceUri, null, (data) { | |
| 356 _loadScript(uri, data); | |
| 357 }); | |
| 358 } else { | |
| 359 var sourceFile = new File(_filePathFromUri(uri)); | |
| 360 sourceFile.readAsBytes().then((data) { | |
| 361 _loadScript(uri, data); | |
| 362 }, | |
| 363 onError: (e) { | |
| 364 _asyncLoadError(uri, null, e); | |
| 365 }); | |
| 366 } | |
| 367 } | |
| 368 | |
| 369 | |
| 370 void _loadLibrarySourceCallback(tag, uri, libraryUri, text) | |
| 371 native "Builtin_LoadLibrarySource"; | |
| 372 | |
| 373 void _loadLibrarySource(tag, uri, libraryUri, text) { | |
| 374 // TODO: Currently a compilation error while loading the library is | |
| 375 // fatal for the isolate. _loadLibraryCallback() does not return and | |
| 376 // the _numOutstandingLoadRequests counter remains out of sync. | |
| 377 _loadLibrarySourceCallback(tag, uri, libraryUri, text); | |
| 378 assert(_numOutstandingLoadRequests > 0); | |
| 379 _numOutstandingLoadRequests--; | |
| 380 _logResolution("native Builtin_LoadLibrarySource($uri) completed, " | |
| 381 "${_numOutstandingLoadRequests} requests remaining"); | |
| 382 if (_numOutstandingLoadRequests == 0) { | |
| 383 _signalDoneLoading(); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 | |
| 388 // Asynchronously loads source code through an http or file uri. | |
| 389 _loadSourceAsync(int tag, String uri, String libraryUri) { | |
| 390 var filePath = _filePathFromUri(uri); | |
| 391 Uri sourceUri = Uri.parse(filePath); | |
| 392 _numOutstandingLoadRequests++; | |
| 393 _logResolution("_loadLibrarySource($uri), " | |
| 394 "${_numOutstandingLoadRequests} requests outstanding"); | |
| 395 if (sourceUri.scheme == 'http') { | |
| 396 _httpGet(sourceUri, libraryUri, (data) { | 299 _httpGet(sourceUri, libraryUri, (data) { |
| 397 var text = UTF8.decode(data); | 300 _loadScript(tag, uri, libraryUri, data); |
| 398 _loadLibrarySource(tag, uri, libraryUri, text); | |
| 399 }); | 301 }); |
| 400 } else { | 302 } else { |
| 401 var sourceFile = new File(filePath); | 303 var sourceFile = new File(filePath); |
| 402 sourceFile.readAsString().then((text) { | 304 sourceFile.readAsBytes().then((data) { |
| 403 _loadLibrarySource(tag, uri, libraryUri, text); | 305 _loadScript(tag, uri, libraryUri, data); |
| 404 }, | 306 }, |
| 405 onError: (e) { | 307 onError: (e) { |
| 406 _asyncLoadError(uri, libraryUri, e); | 308 _asyncLoadError(uri, libraryUri, e); |
| 407 }); | 309 }); |
| 408 } | 310 } |
| 409 } | 311 } |
| 410 | 312 |
| 411 | |
| 412 // Returns the directory part, the filename part, and the name | 313 // Returns the directory part, the filename part, and the name |
| 413 // of a native extension URL as a list [directory, filename, name]. | 314 // of a native extension URL as a list [directory, filename, name]. |
| 414 // The directory part is either a file system path or an HTTP(S) URL. | 315 // The directory part is either a file system path or an HTTP(S) URL. |
| 415 // The filename part is the extension name, with the platform-dependent | 316 // The filename part is the extension name, with the platform-dependent |
| 416 // prefixes and extensions added. | 317 // prefixes and extensions added. |
| 417 _extensionPathFromUri(String userUri) { | 318 _extensionPathFromUri(String userUri) { |
| 418 if (!userUri.startsWith(_DART_EXT)) { | 319 if (!userUri.startsWith(_DART_EXT)) { |
| 419 throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:'; | 320 throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:'; |
| 420 } | 321 } |
| 421 userUri = userUri.substring(_DART_EXT.length); | 322 userUri = userUri.substring(_DART_EXT.length); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 447 } else if (Platform.isWindows) { | 348 } else if (Platform.isWindows) { |
| 448 filename = '$name.dll'; | 349 filename = '$name.dll'; |
| 449 } else { | 350 } else { |
| 450 _logResolution( | 351 _logResolution( |
| 451 'Native extensions not supported on ${Platform.operatingSystem}'); | 352 'Native extensions not supported on ${Platform.operatingSystem}'); |
| 452 throw 'Native extensions not supported on ${Platform.operatingSystem}'; | 353 throw 'Native extensions not supported on ${Platform.operatingSystem}'; |
| 453 } | 354 } |
| 454 | 355 |
| 455 return [path, filename, name]; | 356 return [path, filename, name]; |
| 456 } | 357 } |
| OLD | NEW |