OLD | NEW |
| (Empty) |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 import 'dart:async'; | |
6 import 'dart:convert'; | |
7 import 'dart:io'; | |
8 | |
9 import 'compiler_configuration.dart'; | |
10 import 'http_server.dart'; | |
11 import 'path.dart'; | |
12 import 'runtime_configuration.dart'; | |
13 import 'test_suite.dart'; | |
14 | |
15 /// All of the contextual information to determine how a test suite should be | |
16 /// run. | |
17 /// | |
18 /// Includes the compiler used to compile the code, the runtime the result is | |
19 /// executed on, etc. | |
20 class Configuration { | |
21 Configuration( | |
22 {this.architecture, | |
23 this.compiler, | |
24 this.mode, | |
25 this.progress, | |
26 this.runtime, | |
27 this.system, | |
28 this.selectors, | |
29 this.appendLogs, | |
30 this.batch, | |
31 this.batchDart2JS, | |
32 this.copyCoreDumps, | |
33 this.hotReload, | |
34 this.hotReloadRollback, | |
35 this.isChecked, | |
36 this.isStrong, | |
37 this.isHostChecked, | |
38 this.isCsp, | |
39 this.isMinified, | |
40 this.isVerbose, | |
41 this.listTests, | |
42 this.printTiming, | |
43 this.printReport, | |
44 this.reportInJson, | |
45 this.resetBrowser, | |
46 this.skipCompilation, | |
47 this.useBlobs, | |
48 this.useSdk, | |
49 this.useFastStartup, | |
50 this.useDart2JSWithKernel, | |
51 this.writeDebugLog, | |
52 this.writeTestOutcomeLog, | |
53 this.drtPath, | |
54 this.dartiumPath, | |
55 this.chromePath, | |
56 this.safariPath, | |
57 this.firefoxPath, | |
58 this.dartPath, | |
59 this.dartPrecompiledPath, | |
60 this.flutterPath, | |
61 this.recordingPath, | |
62 this.replayPath, | |
63 this.taskCount, | |
64 int timeout, | |
65 this.shardCount, | |
66 this.shard, | |
67 this.stepName, | |
68 this.testServerPort, | |
69 this.testServerCrossOriginPort, | |
70 this.testDriverErrorPort, | |
71 this.localIP, | |
72 this.dart2jsOptions, | |
73 this.vmOptions, | |
74 String packages, | |
75 this.packageRoot, | |
76 this.suiteDirectory, | |
77 this.builderTag, | |
78 this.reproducingArguments}) | |
79 : _packages = packages, | |
80 _timeout = timeout; | |
81 | |
82 final Architecture architecture; | |
83 final Compiler compiler; | |
84 final Mode mode; | |
85 final Progress progress; | |
86 final Runtime runtime; | |
87 final System system; | |
88 | |
89 final Map<String, RegExp> selectors; | |
90 | |
91 // Boolean flags. | |
92 | |
93 final bool appendLogs; | |
94 final bool batch; | |
95 final bool batchDart2JS; | |
96 final bool copyCoreDumps; | |
97 final bool hotReload; | |
98 final bool hotReloadRollback; | |
99 final bool isChecked; | |
100 final bool isStrong; | |
101 final bool isHostChecked; | |
102 final bool isCsp; | |
103 final bool isMinified; | |
104 final bool isVerbose; | |
105 final bool listTests; | |
106 final bool printTiming; | |
107 final bool printReport; | |
108 final bool reportInJson; | |
109 final bool resetBrowser; | |
110 final bool skipCompilation; | |
111 final bool useBlobs; | |
112 final bool useSdk; | |
113 final bool useFastStartup; | |
114 final bool useDart2JSWithKernel; | |
115 final bool writeDebugLog; | |
116 final bool writeTestOutcomeLog; | |
117 | |
118 // Various file paths. | |
119 | |
120 final String drtPath; | |
121 final String dartiumPath; | |
122 final String chromePath; | |
123 final String safariPath; | |
124 final String firefoxPath; | |
125 final String dartPath; | |
126 final String dartPrecompiledPath; | |
127 final String flutterPath; | |
128 final String recordingPath; | |
129 final String replayPath; | |
130 | |
131 final int taskCount; | |
132 final int shardCount; | |
133 final int shard; | |
134 final String stepName; | |
135 | |
136 final int testServerPort; | |
137 final int testServerCrossOriginPort; | |
138 final int testDriverErrorPort; | |
139 final String localIP; | |
140 | |
141 /// Extra dart2js options passed to the testing script. | |
142 final List<String> dart2jsOptions; | |
143 | |
144 /// Extra VM options passed to the testing script. | |
145 final List<String> vmOptions; | |
146 | |
147 String _packages; | |
148 String get packages { | |
149 // If the .packages file path wasn't given, find it. | |
150 if (packageRoot == null && _packages == null) { | |
151 _packages = TestUtils.dartDirUri.resolve('.packages').toFilePath(); | |
152 } | |
153 | |
154 return _packages; | |
155 } | |
156 | |
157 final String packageRoot; | |
158 final String suiteDirectory; | |
159 final String builderTag; | |
160 final List<String> reproducingArguments; | |
161 | |
162 TestingServers _servers; | |
163 TestingServers get servers { | |
164 if (_servers == null) { | |
165 throw new StateError("Servers have not been started yet."); | |
166 } | |
167 return _servers; | |
168 } | |
169 | |
170 /// The base directory named for this configuration, like: | |
171 /// | |
172 /// none_vm_release_x64 | |
173 String _configurationDirectory; | |
174 String get configurationDirectory { | |
175 // Lazy initialize and cache since it requires hitting the file system. | |
176 if (_configurationDirectory == null) { | |
177 _configurationDirectory = _calculateDirectory(); | |
178 } | |
179 | |
180 return _configurationDirectory; | |
181 } | |
182 | |
183 /// The build directory path for this configuration, like: | |
184 /// | |
185 /// build/none_vm_release_x64 | |
186 String get buildDirectory => system.outputDirectory + configurationDirectory; | |
187 | |
188 int _timeout; | |
189 int get timeout { | |
190 if (_timeout == null) { | |
191 var isReload = hotReload || hotReloadRollback; | |
192 | |
193 var compilerMulitiplier = compilerConfiguration.timeoutMultiplier; | |
194 var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier( | |
195 mode: mode, | |
196 isChecked: isChecked, | |
197 isReload: isReload, | |
198 arch: architecture); | |
199 | |
200 _timeout = 60 * compilerMulitiplier * runtimeMultiplier; | |
201 } | |
202 | |
203 return _timeout; | |
204 } | |
205 | |
206 List<String> get standardOptions { | |
207 if (compiler != Compiler.dart2js) { | |
208 return const ["--ignore-unrecognized-flags"]; | |
209 } | |
210 | |
211 var args = ['--generate-code-with-compile-time-errors', '--test-mode']; | |
212 if (isChecked) args.add('--enable-checked-mode'); | |
213 | |
214 if (!runtime.isBrowser) { | |
215 args.add("--allow-mock-compilation"); | |
216 args.add("--categories=all"); | |
217 } | |
218 | |
219 if (isMinified) args.add("--minify"); | |
220 if (isCsp) args.add("--csp"); | |
221 if (useFastStartup) args.add("--fast-startup"); | |
222 if (useDart2JSWithKernel) args.add("--use-kernel"); | |
223 return args; | |
224 } | |
225 | |
226 String _windowsSdkPath; | |
227 String get windowsSdkPath { | |
228 if (!Platform.isWindows) { | |
229 throw new StateError( | |
230 "Should not use windowsSdkPath when not running on Windows."); | |
231 } | |
232 | |
233 if (_windowsSdkPath == null) { | |
234 // When running tests on Windows, use cdb from depot_tools to dump | |
235 // stack traces of tests timing out. | |
236 try { | |
237 var path = new Path("build/win_toolchain.json").toNativePath(); | |
238 var text = new File(path).readAsStringSync(); | |
239 _windowsSdkPath = JSON.decode(text)['win_sdk'] as String; | |
240 } on dynamic { | |
241 // Ignore errors here. If win_sdk is not found, stack trace dumping | |
242 // for timeouts won't work. | |
243 } | |
244 } | |
245 | |
246 return _windowsSdkPath; | |
247 } | |
248 | |
249 /// Gets the local file path to the browser executable for this configuration. | |
250 String get browserLocation { | |
251 // If the user has explicitly configured a browser path, use it. | |
252 String location; | |
253 switch (runtime) { | |
254 case Runtime.chrome: | |
255 location = chromePath; | |
256 break; | |
257 case Runtime.dartium: | |
258 location = dartiumPath; | |
259 break; | |
260 case Runtime.drt: | |
261 location = drtPath; | |
262 break; | |
263 case Runtime.firefox: | |
264 location = firefoxPath; | |
265 break; | |
266 case Runtime.flutter: | |
267 location = flutterPath; | |
268 break; | |
269 case Runtime.safari: | |
270 location = safariPath; | |
271 break; | |
272 } | |
273 | |
274 if (location != null) return location; | |
275 | |
276 const locations = const { | |
277 Runtime.firefox: const { | |
278 System.windows: 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe', | |
279 System.linux: 'firefox', | |
280 System.macos: '/Applications/Firefox.app/Contents/MacOS/firefox' | |
281 }, | |
282 Runtime.chrome: const { | |
283 System.windows: | |
284 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', | |
285 System.macos: | |
286 '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', | |
287 System.linux: 'google-chrome' | |
288 }, | |
289 Runtime.dartium: const { | |
290 System.windows: 'client\\tests\\dartium\\chrome.exe', | |
291 System.macos: | |
292 'client/tests/dartium/Chromium.app/Contents/MacOS/Chromium', | |
293 System.linux: 'client/tests/dartium/chrome' | |
294 }, | |
295 Runtime.safari: const { | |
296 System.macos: '/Applications/Safari.app/Contents/MacOS/Safari' | |
297 }, | |
298 Runtime.safariMobileSim: const { | |
299 System.macos: '/Applications/Xcode.app/Contents/Developer/Platforms/' | |
300 'iPhoneSimulator.platform/Developer/Applications/' | |
301 'iPhone Simulator.app/Contents/MacOS/iPhone Simulator' | |
302 }, | |
303 Runtime.ie9: const { | |
304 System.windows: 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | |
305 }, | |
306 Runtime.ie10: const { | |
307 System.windows: 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | |
308 }, | |
309 Runtime.ie11: const { | |
310 System.windows: 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | |
311 } | |
312 }; | |
313 | |
314 location = locations[runtime][System.find(Platform.operatingSystem)]; | |
315 | |
316 if (location == null) { | |
317 throw "${runtime.name} is not supported on ${Platform.operatingSystem}"; | |
318 } | |
319 | |
320 return location; | |
321 } | |
322 | |
323 RuntimeConfiguration _runtimeConfiguration; | |
324 RuntimeConfiguration get runtimeConfiguration => | |
325 _runtimeConfiguration ??= new RuntimeConfiguration(this); | |
326 | |
327 CompilerConfiguration _compilerConfiguration; | |
328 CompilerConfiguration get compilerConfiguration => | |
329 _compilerConfiguration ??= new CompilerConfiguration(this); | |
330 | |
331 /// Determines if this configuration has a compatible compiler and runtime | |
332 /// and other valid fields. | |
333 /// | |
334 /// Prints a warning if the configuration isn't valid. Returns whether or not | |
335 /// it is. | |
336 bool validate() { | |
337 var isValid = true; | |
338 var validRuntimes = compiler.supportedRuntimes; | |
339 | |
340 if (!validRuntimes.contains(runtime)) { | |
341 print("Warning: combination of compiler '${compiler.name}' and " | |
342 "runtime '${runtime.name}' is invalid. Skipping this combination."); | |
343 isValid = false; | |
344 } | |
345 | |
346 if (runtime.isIE && Platform.operatingSystem != 'windows') { | |
347 print("Warning: cannot run Internet Explorer on non-Windows operating" | |
348 " system."); | |
349 isValid = false; | |
350 } | |
351 | |
352 if (shard < 1 || shard > shardCount) { | |
353 print("Error: shard index is $shard out of $shardCount shards"); | |
354 isValid = false; | |
355 } | |
356 | |
357 if (runtime == Runtime.flutter && flutterPath == null) { | |
358 print("-rflutter requires the flutter engine executable to " | |
359 "be specified using --flutter"); | |
360 isValid = false; | |
361 } | |
362 | |
363 if (runtime == Runtime.flutter && architecture != Architecture.x64) { | |
364 isValid = false; | |
365 print("-rflutter is applicable only for --arch=x64"); | |
366 } | |
367 | |
368 return isValid; | |
369 } | |
370 | |
371 /// Starts global HTTP servers that serve the entire dart repo. | |
372 /// | |
373 /// The HTTP server is available on `window.location.port`, and a second | |
374 /// server for cross-domain tests can be found by calling | |
375 /// `getCrossOriginPortNumber()`. | |
376 Future startServers() { | |
377 _servers = new TestingServers( | |
378 buildDirectory, isCsp, runtime, null, packageRoot, packages); | |
379 var future = servers.startServers(localIP, | |
380 port: testServerPort, crossOriginPort: testServerCrossOriginPort); | |
381 | |
382 if (isVerbose) { | |
383 future = future.then((_) { | |
384 print('Started HttpServers: ${servers.httpServerCommandLine()}'); | |
385 }); | |
386 } | |
387 | |
388 return future; | |
389 } | |
390 | |
391 void stopServers() { | |
392 if (_servers != null) _servers.stopServers(); | |
393 } | |
394 | |
395 /// Returns the correct configuration directory (the last component of the | |
396 /// output directory path) for regular dart checkouts. | |
397 /// | |
398 /// Dartium checkouts use the `--build-directory` option to pass in the | |
399 /// correct build directory explicitly. We allow our code to have been cross | |
400 /// compiled, i.e., that there is an X in front of the arch. We don't allow | |
401 /// both a cross compiled and a normal version to be present (except if you | |
402 /// specifically pass in the build_directory). | |
403 String _calculateDirectory() { | |
404 // Capitalize the mode name. | |
405 var modeName = | |
406 mode.name.substring(0, 1).toUpperCase() + mode.name.substring(1); | |
407 | |
408 var os = ''; | |
409 if (system == System.android) os = "Android"; | |
410 | |
411 var arch = architecture.name.toUpperCase(); | |
412 var normal = '$modeName$os$arch'; | |
413 var cross = '$modeName${os}X$arch'; | |
414 var outDir = system.outputDirectory; | |
415 var normalDir = new Directory(new Path('$outDir$normal').toNativePath()); | |
416 var crossDir = new Directory(new Path('$outDir$cross').toNativePath()); | |
417 | |
418 if (normalDir.existsSync() && crossDir.existsSync()) { | |
419 throw "You can't have both $normalDir and $crossDir. We don't know which" | |
420 " binary to use."; | |
421 } | |
422 | |
423 if (crossDir.existsSync()) return cross; | |
424 | |
425 return normal; | |
426 } | |
427 } | |
428 | |
429 class Architecture { | |
430 static const ia32 = const Architecture._('ia32'); | |
431 static const x64 = const Architecture._('x64'); | |
432 static const arm = const Architecture._('arm'); | |
433 static const armv6 = const Architecture._('armv6'); | |
434 static const armv5te = const Architecture._('armv5te'); | |
435 static const arm64 = const Architecture._('arm64'); | |
436 static const simarm = const Architecture._('simarm'); | |
437 static const simarmv6 = const Architecture._('simarmv6'); | |
438 static const simarmv5te = const Architecture._('simarmv5te'); | |
439 static const simarm64 = const Architecture._('simarm64'); | |
440 static const mips = const Architecture._('mips'); | |
441 static const simmips = const Architecture._('simmips'); | |
442 static const simdbc = const Architecture._('simdbc'); | |
443 static const simdbc64 = const Architecture._('simdbc64'); | |
444 | |
445 static final List<String> names = _all.keys.toList(); | |
446 | |
447 static final _all = new Map<String, Architecture>.fromIterable([ | |
448 ia32, | |
449 x64, | |
450 arm, | |
451 armv6, | |
452 armv5te, | |
453 arm64, | |
454 simarm, | |
455 simarmv6, | |
456 simarmv5te, | |
457 simarm64, | |
458 mips, | |
459 simmips, | |
460 simdbc, | |
461 simdbc64 | |
462 ], key: (Architecture architecture) => architecture.name); | |
463 | |
464 static Architecture find(String name) { | |
465 var architecture = _all[name]; | |
466 if (architecture != null) return architecture; | |
467 | |
468 throw new ArgumentError('Unknown architecture "$name".'); | |
469 } | |
470 | |
471 final String name; | |
472 | |
473 const Architecture._(this.name); | |
474 | |
475 String toString() => "Architecture($name)"; | |
476 } | |
477 | |
478 class Compiler { | |
479 static const none = const Compiler._('none'); | |
480 static const precompiler = const Compiler._('precompiler'); | |
481 static const dart2js = const Compiler._('dart2js'); | |
482 static const dart2analyzer = const Compiler._('dart2analyzer'); | |
483 static const appJit = const Compiler._('app_jit'); | |
484 static const dartk = const Compiler._('dartk'); | |
485 static const dartkp = const Compiler._('dartkp'); | |
486 | |
487 static final List<String> names = _all.keys.toList(); | |
488 | |
489 static final _all = new Map<String, Compiler>.fromIterable( | |
490 [none, precompiler, dart2js, dart2analyzer, appJit, dartk, dartkp], | |
491 key: (Compiler compiler) => compiler.name); | |
492 | |
493 static Compiler find(String name) { | |
494 var compiler = _all[name]; | |
495 if (compiler != null) return compiler; | |
496 | |
497 throw new ArgumentError('Unknown compiler "$name".'); | |
498 } | |
499 | |
500 final String name; | |
501 | |
502 const Compiler._(this.name); | |
503 | |
504 /// Gets the runtimes this compiler can target. | |
505 List<Runtime> get supportedRuntimes { | |
506 switch (this) { | |
507 case Compiler.dart2js: | |
508 // Note: by adding 'none' as a configuration, if the user | |
509 // runs test.py -c dart2js -r drt,none the dart2js_none and | |
510 // dart2js_drt will be duplicating work. If later we don't need 'none' | |
511 // with dart2js, we should remove it from here. | |
512 return const [ | |
513 Runtime.d8, | |
514 Runtime.jsshell, | |
515 Runtime.drt, | |
516 Runtime.none, | |
517 Runtime.dartium, | |
518 Runtime.firefox, | |
519 Runtime.chrome, | |
520 Runtime.safari, | |
521 Runtime.ie9, | |
522 Runtime.ie10, | |
523 Runtime.ie11, | |
524 Runtime.opera, | |
525 Runtime.chromeOnAndroid, | |
526 Runtime.safariMobileSim | |
527 ]; | |
528 | |
529 case Compiler.dart2analyzer: | |
530 return const [Runtime.none]; | |
531 case Compiler.appJit: | |
532 case Compiler.dartk: | |
533 return const [Runtime.vm, Runtime.selfCheck, Runtime.none]; | |
534 case Compiler.precompiler: | |
535 case Compiler.dartkp: | |
536 return const [Runtime.dartPrecompiled]; | |
537 case Compiler.none: | |
538 return const [ | |
539 Runtime.vm, | |
540 Runtime.flutter, | |
541 Runtime.drt, | |
542 Runtime.dartium, | |
543 Runtime.contentShellOnAndroid, | |
544 Runtime.dartiumOnAndroid | |
545 ]; | |
546 } | |
547 | |
548 throw "unreachable"; | |
549 } | |
550 | |
551 String toString() => "Compiler($name)"; | |
552 } | |
553 | |
554 class Mode { | |
555 static const debug = const Mode._('debug'); | |
556 static const product = const Mode._('product'); | |
557 static const release = const Mode._('release'); | |
558 | |
559 static final List<String> names = _all.keys.toList(); | |
560 | |
561 static final _all = new Map<String, Mode>.fromIterable( | |
562 [debug, product, release], | |
563 key: (Mode mode) => mode.name); | |
564 | |
565 static Mode find(String name) { | |
566 var mode = _all[name]; | |
567 if (mode != null) return mode; | |
568 | |
569 throw new ArgumentError('Unknown mode "$name".'); | |
570 } | |
571 | |
572 final String name; | |
573 | |
574 const Mode._(this.name); | |
575 | |
576 bool get isDebug => this == debug; | |
577 | |
578 String toString() => "Mode($name)"; | |
579 } | |
580 | |
581 class Progress { | |
582 static const compact = const Progress._('compact'); | |
583 static const color = const Progress._('color'); | |
584 static const line = const Progress._('line'); | |
585 static const verbose = const Progress._('verbose'); | |
586 static const silent = const Progress._('silent'); | |
587 static const status = const Progress._('status'); | |
588 static const buildbot = const Progress._('buildbot'); | |
589 static const diff = const Progress._('diff'); | |
590 | |
591 static final List<String> names = _all.keys.toList(); | |
592 | |
593 static final _all = new Map<String, Progress>.fromIterable( | |
594 [compact, color, line, verbose, silent, status, buildbot, diff], | |
595 key: (Progress progress) => progress.name); | |
596 | |
597 static Progress find(String name) { | |
598 var progress = _all[name]; | |
599 if (progress != null) return progress; | |
600 | |
601 throw new ArgumentError('Unknown progress type "$name".'); | |
602 } | |
603 | |
604 final String name; | |
605 | |
606 const Progress._(this.name); | |
607 | |
608 String toString() => "Progress($name)"; | |
609 } | |
610 | |
611 class Runtime { | |
612 static const vm = const Runtime._('vm'); | |
613 static const flutter = const Runtime._('flutter'); | |
614 static const dartPrecompiled = const Runtime._('dart_precompiled'); | |
615 static const d8 = const Runtime._('d8'); | |
616 static const jsshell = const Runtime._('jsshell'); | |
617 static const drt = const Runtime._('drt'); | |
618 static const dartium = const Runtime._('dartium'); | |
619 static const firefox = const Runtime._('firefox'); | |
620 static const chrome = const Runtime._('chrome'); | |
621 static const safari = const Runtime._('safari'); | |
622 static const ie9 = const Runtime._('ie9'); | |
623 static const ie10 = const Runtime._('ie10'); | |
624 static const ie11 = const Runtime._('ie11'); | |
625 static const opera = const Runtime._('opera'); | |
626 static const chromeOnAndroid = const Runtime._('chromeOnAndroid'); | |
627 static const safariMobileSim = const Runtime._('safarimobilesim'); | |
628 static const contentShellOnAndroid = const Runtime._('ContentShellOnAndroid'); | |
629 static const dartiumOnAndroid = const Runtime._('DartiumOnAndroid'); | |
630 static const selfCheck = const Runtime._('self_check'); | |
631 static const none = const Runtime._('none'); | |
632 | |
633 static final List<String> names = _all.keys.toList()..add("ff"); | |
634 | |
635 static final _all = new Map<String, Runtime>.fromIterable([ | |
636 vm, | |
637 flutter, | |
638 dartPrecompiled, | |
639 d8, | |
640 jsshell, | |
641 drt, | |
642 dartium, | |
643 firefox, | |
644 chrome, | |
645 safari, | |
646 ie9, | |
647 ie10, | |
648 ie11, | |
649 opera, | |
650 chromeOnAndroid, | |
651 safariMobileSim, | |
652 contentShellOnAndroid, | |
653 dartiumOnAndroid, | |
654 selfCheck, | |
655 none | |
656 ], key: (Runtime runtime) => runtime.name); | |
657 | |
658 static Runtime find(String name) { | |
659 // Allow "ff" as a synonym for Firefox. | |
660 if (name == "ff") return firefox; | |
661 | |
662 var runtime = _all[name]; | |
663 if (runtime != null) return runtime; | |
664 | |
665 throw new ArgumentError('Unknown runtime "$name".'); | |
666 } | |
667 | |
668 final String name; | |
669 | |
670 const Runtime._(this.name); | |
671 | |
672 bool get isBrowser => const [ | |
673 drt, | |
674 dartium, | |
675 ie9, | |
676 ie10, | |
677 ie11, | |
678 safari, | |
679 opera, | |
680 chrome, | |
681 firefox, | |
682 chromeOnAndroid, | |
683 safariMobileSim, | |
684 contentShellOnAndroid, | |
685 dartiumOnAndroid, | |
686 ].contains(this); | |
687 | |
688 bool get isIE => name.startsWith("ie"); | |
689 bool get isSafari => name.startsWith("safari"); | |
690 | |
691 /// Whether this runtime is a command-line JavaScript environment. | |
692 bool get isJSCommandLine => const [d8, jsshell].contains(this); | |
693 | |
694 /// If the runtime doesn't support `Window.open`, we use iframes instead. | |
695 bool get requiresIFrame => !const [ie11, ie10].contains(this); | |
696 | |
697 String toString() => "Runtime($name)"; | |
698 } | |
699 | |
700 class System { | |
701 static const android = const System._('android'); | |
702 static const fuchsia = const System._('fuchsia'); | |
703 static const linux = const System._('linux'); | |
704 static const macos = const System._('macos'); | |
705 static const windows = const System._('windows'); | |
706 | |
707 static final List<String> names = _all.keys.toList(); | |
708 | |
709 static final _all = new Map<String, System>.fromIterable( | |
710 [android, fuchsia, linux, macos, windows], | |
711 key: (System system) => system.name); | |
712 | |
713 static System find(String name) { | |
714 var system = _all[name]; | |
715 if (system != null) return system; | |
716 | |
717 throw new ArgumentError('Unknown operating system "$name".'); | |
718 } | |
719 | |
720 final String name; | |
721 | |
722 const System._(this.name); | |
723 | |
724 /// The root directory name for build outputs on this system. | |
725 String get outputDirectory { | |
726 switch (this) { | |
727 case android: | |
728 case fuchsia: | |
729 case linux: | |
730 case windows: | |
731 return 'out/'; | |
732 | |
733 case macos: | |
734 return 'xcodebuild/'; | |
735 } | |
736 | |
737 throw "unreachable"; | |
738 } | |
739 | |
740 String toString() => "System($name)"; | |
741 } | |
OLD | NEW |