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.util.dart; | 5 library test.util.dart; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | |
9 import 'dart:isolate'; | 8 import 'dart:isolate'; |
10 | 9 |
11 import 'package:analyzer/analyzer.dart'; | 10 import 'package:analyzer/analyzer.dart'; |
12 import 'package:path/path.dart' as p; | |
13 import 'package:source_span/source_span.dart'; | 11 import 'package:source_span/source_span.dart'; |
14 | 12 |
15 import 'string_literal_iterator.dart'; | 13 import 'string_literal_iterator.dart'; |
16 import 'io.dart'; | |
17 import 'isolate_wrapper.dart'; | |
18 | 14 |
19 /// Runs [code] in an isolate. | 15 /// Runs [code] in an isolate. |
20 /// | 16 /// |
21 /// [code] should be the contents of a Dart entrypoint. It may contain imports; | 17 /// [code] should be the contents of a Dart entrypoint. It may contain imports; |
22 /// they will be resolved in the same context as the host isolate. [message] is | 18 /// they will be resolved in the same context as the host isolate. [message] is |
23 /// passed to the [main] method of the code being run; the caller is responsible | 19 /// passed to the [main] method of the code being run; the caller is responsible |
24 /// for using this to establish communication with the isolate. | 20 /// for using this to establish communication with the isolate. |
25 /// | 21 /// |
26 /// [packageRoot] controls the package root of the isolate. It may be either a | 22 /// [packageRoot] controls the package root of the isolate. It may be either a |
27 /// [String] or a [Uri]. | 23 /// [String] or a [Uri]. |
28 Future<IsolateWrapper> runInIsolate(String code, message, {packageRoot, | 24 Future<Isolate> runInIsolate(String code, message, {packageRoot, |
29 bool checked}) async { | 25 bool checked}) async { |
30 // TODO(nweiz): load code from a local server rather than from a file. | 26 if (packageRoot is String) packageRoot = Uri.parse(packageRoot); |
31 var dir = createTempDir(); | |
32 var dartPath = p.join(dir, 'runInIsolate.dart'); | |
33 new File(dartPath).writeAsStringSync(code); | |
34 | 27 |
35 return await spawnUri( | 28 return await Isolate.spawnUri( |
36 p.toUri(dartPath), message, | 29 Uri.parse('data:application/dart;charset=utf-8,' + Uri.encodeFull(code)), |
| 30 [], |
| 31 message, |
37 packageRoot: packageRoot, | 32 packageRoot: packageRoot, |
38 checked: checked, | 33 checked: checked); |
39 onExit: () => new Directory(dir).deleteSync(recursive: true)); | |
40 } | |
41 | |
42 /// Like [Isolate.spawnUri], except that [uri] and [packageRoot] may be strings, | |
43 /// [checked] mode is silently ignored on older Dart versions, and [onExit] is | |
44 /// run after the isolate is killed. | |
45 /// | |
46 /// If the isolate fails to load, [onExit] will also be run. | |
47 Future<IsolateWrapper> spawnUri(uri, message, {packageRoot, bool checked, | |
48 void onExit()}) async { | |
49 if (uri is String) uri = Uri.parse(uri); | |
50 if (packageRoot is String) packageRoot = Uri.parse(packageRoot); | |
51 if (onExit == null) onExit = () {}; | |
52 | |
53 try { | |
54 var isolate = supportsIsolateCheckedMode | |
55 ? await Isolate.spawnUri( | |
56 uri, [], message, checked: checked, packageRoot: packageRoot) | |
57 : await Isolate.spawnUri( | |
58 uri, [], message, packageRoot: packageRoot); | |
59 return new IsolateWrapper(isolate, onExit); | |
60 } catch (error) { | |
61 onExit(); | |
62 rethrow; | |
63 } | |
64 } | 34 } |
65 | 35 |
66 // TODO(nweiz): Move this into the analyzer once it starts using SourceSpan | 36 // TODO(nweiz): Move this into the analyzer once it starts using SourceSpan |
67 // (issue 22977). | 37 // (issue 22977). |
68 /// Takes a span whose source is the value of a string that has been parsed from | 38 /// Takes a span whose source is the value of a string that has been parsed from |
69 /// a Dart file and returns the corresponding span from within that Dart file. | 39 /// a Dart file and returns the corresponding span from within that Dart file. |
70 /// | 40 /// |
71 /// For example, suppose a Dart file contains `@Eval("1 + a")`. The | 41 /// For example, suppose a Dart file contains `@Eval("1 + a")`. The |
72 /// [StringLiteral] `"1 + a"` is extracted; this is [context]. Its contents are | 42 /// [StringLiteral] `"1 + a"` is extracted; this is [context]. Its contents are |
73 /// then parsed, producing an error pointing to [span]: | 43 /// then parsed, producing an error pointing to [span]: |
(...skipping 25 matching lines...) Expand all Loading... |
99 } | 69 } |
100 | 70 |
101 var start = contextRunes.offset; | 71 var start = contextRunes.offset; |
102 for (var spanRune in span.text.runes) { | 72 for (var spanRune in span.text.runes) { |
103 if (spanRune != contextRunes.current) return null; | 73 if (spanRune != contextRunes.current) return null; |
104 contextRunes.moveNext(); | 74 contextRunes.moveNext(); |
105 } | 75 } |
106 | 76 |
107 return file.span(start, contextRunes.offset); | 77 return file.span(start, contextRunes.offset); |
108 } | 78 } |
OLD | NEW |