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 library test.runner.browser.server; | 5 library test.runner.browser.server; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
| 11 import 'package:async/async.dart'; |
11 import 'package:http_multi_server/http_multi_server.dart'; | 12 import 'package:http_multi_server/http_multi_server.dart'; |
12 import 'package:path/path.dart' as p; | 13 import 'package:path/path.dart' as p; |
13 import 'package:pool/pool.dart'; | 14 import 'package:pool/pool.dart'; |
14 import 'package:shelf/shelf.dart' as shelf; | 15 import 'package:shelf/shelf.dart' as shelf; |
15 import 'package:shelf/shelf_io.dart' as shelf_io; | 16 import 'package:shelf/shelf_io.dart' as shelf_io; |
16 import 'package:shelf_static/shelf_static.dart'; | 17 import 'package:shelf_static/shelf_static.dart'; |
17 import 'package:shelf_web_socket/shelf_web_socket.dart'; | 18 import 'package:shelf_web_socket/shelf_web_socket.dart'; |
18 | 19 |
19 import '../../backend/metadata.dart'; | 20 import '../../backend/metadata.dart'; |
20 import '../../backend/suite.dart'; | 21 import '../../backend/suite.dart'; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 | 128 |
128 /// The thunk for running [close] exactly once. | 129 /// The thunk for running [close] exactly once. |
129 final _closeThunk = new AsyncThunk(); | 130 final _closeThunk = new AsyncThunk(); |
130 | 131 |
131 /// All currently-running browsers. | 132 /// All currently-running browsers. |
132 /// | 133 /// |
133 /// These are controlled by [_browserManager]s. | 134 /// These are controlled by [_browserManager]s. |
134 final _browsers = new Map<TestPlatform, Browser>(); | 135 final _browsers = new Map<TestPlatform, Browser>(); |
135 | 136 |
136 /// A map from browser identifiers to futures that will complete to the | 137 /// A map from browser identifiers to futures that will complete to the |
137 /// [BrowserManager]s for those browsers. | 138 /// [BrowserManager]s for those browsers, or the errors that occurred when |
| 139 /// trying to load those managers. |
138 /// | 140 /// |
139 /// This should only be accessed through [_browserManagerFor]. | 141 /// This should only be accessed through [_browserManagerFor]. |
140 final _browserManagers = new Map<TestPlatform, Future<BrowserManager>>(); | 142 final _browserManagers = |
| 143 new Map<TestPlatform, Future<Result<BrowserManager>>>(); |
141 | 144 |
142 /// A map from test suite paths to Futures that will complete once those | 145 /// A map from test suite paths to Futures that will complete once those |
143 /// suites are finished compiling. | 146 /// suites are finished compiling. |
144 /// | 147 /// |
145 /// This is used to make sure that a given test suite is only compiled once | 148 /// This is used to make sure that a given test suite is only compiled once |
146 /// per run, rather than once per browser per run. | 149 /// per run, rather than once per browser per run. |
147 final _compileFutures = new Map<String, Future>(); | 150 final _compileFutures = new Map<String, Future>(); |
148 | 151 |
149 final _mappers = new Map<String, StackTraceMapper>(); | 152 final _mappers = new Map<String, StackTraceMapper>(); |
150 | 153 |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 packageRoot: p.toUri(_packageRoot), | 404 packageRoot: p.toUri(_packageRoot), |
402 sdkRoot: p.toUri(sdkDir)); | 405 sdkRoot: p.toUri(sdkDir)); |
403 }); | 406 }); |
404 } | 407 } |
405 | 408 |
406 /// Returns the [BrowserManager] for [platform], which should be a browser. | 409 /// Returns the [BrowserManager] for [platform], which should be a browser. |
407 /// | 410 /// |
408 /// If no browser manager is running yet, starts one. | 411 /// If no browser manager is running yet, starts one. |
409 Future<BrowserManager> _browserManagerFor(TestPlatform platform) { | 412 Future<BrowserManager> _browserManagerFor(TestPlatform platform) { |
410 var manager = _browserManagers[platform]; | 413 var manager = _browserManagers[platform]; |
411 if (manager != null) return manager; | 414 if (manager != null) return Result.release(manager); |
412 | 415 |
413 var completer = new Completer(); | 416 var completer = new Completer(); |
414 | 417 |
415 // Swallow errors, since they're already being surfaced through the return | 418 // Capture errors and release them later to avoid Zone issues. This call to |
416 // value and [browser.onError]. | 419 // [_browserManagerFor] is running in a different [LoadSuite] than future |
417 _browserManagers[platform] = completer.future.catchError((_) {}); | 420 // calls, which means they're also running in different error zones so |
| 421 // errors can't be freely passed between them. Storing the error or value as |
| 422 // an explicit [Result] fixes that. |
| 423 _browserManagers[platform] = Result.capture(completer.future); |
418 var path = _webSocketHandler.create(webSocketHandler((webSocket) { | 424 var path = _webSocketHandler.create(webSocketHandler((webSocket) { |
419 completer.complete(new BrowserManager(platform, webSocket)); | 425 completer.complete(new BrowserManager(platform, webSocket)); |
420 })); | 426 })); |
421 | 427 |
422 var webSocketUrl = url.replace(scheme: 'ws').resolve(path); | 428 var webSocketUrl = url.replace(scheme: 'ws').resolve(path); |
423 | 429 |
424 var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl) | 430 var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl) |
425 .resolve('packages/test/src/runner/browser/static/index.html'); | 431 .resolve('packages/test/src/runner/browser/static/index.html'); |
426 | 432 |
427 var browser = _newBrowser(hostUrl.replace(queryParameters: { | 433 var browser = _newBrowser(hostUrl.replace(queryParameters: { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 await Future.wait(futures); | 481 await Future.wait(futures); |
476 | 482 |
477 if (_pubServeUrl == null) { | 483 if (_pubServeUrl == null) { |
478 new Directory(_compiledDir).deleteSync(recursive: true); | 484 new Directory(_compiledDir).deleteSync(recursive: true); |
479 } else { | 485 } else { |
480 _http.close(); | 486 _http.close(); |
481 } | 487 } |
482 }); | 488 }); |
483 } | 489 } |
484 } | 490 } |
OLD | NEW |