OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, 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 library pub.asset.transformer_isolate; | |
6 | |
7 import 'dart:convert'; | |
8 import 'dart:isolate'; | |
9 import 'dart:mirrors'; | |
10 | |
11 import 'package:barback/barback.dart'; | |
12 | |
13 import 'serialize.dart'; | |
14 | |
15 /// The mirror system. | |
16 /// | |
17 /// Cached to avoid re-instantiating each time a transformer is initialized. | |
18 final _mirrors = currentMirrorSystem(); | |
19 | |
20 /// Sets up the initial communication with the host isolate. | |
21 void loadTransformers(SendPort replyTo) { | |
22 var port = new ReceivePort(); | |
23 replyTo.send(port.sendPort); | |
24 port.listen((wrappedMessage) { | |
25 // TODO(nweiz): When issue 19228 is fixed, spin up a separate isolate for | |
26 // libraries loaded beyond the first so they can run in parallel. | |
27 respond(wrappedMessage, (message) { | |
28 var configuration = JSON.decode(message['configuration']); | |
29 var mode = new BarbackMode(message['mode']); | |
30 return _initialize(message['library'], configuration, mode). | |
31 map(serializeTransformerLike).toList(); | |
32 }); | |
33 }); | |
34 } | |
35 | |
36 /// Loads all the transformers and groups defined in [uri]. | |
37 /// | |
38 /// Loads the library, finds any [Transformer] or [TransformerGroup] subclasses | |
39 /// in it, instantiates them with [configuration] and [mode], and returns them. | |
40 List _initialize(String uri, Map configuration, BarbackMode mode) { | |
41 var transformerClass = reflectClass(Transformer); | |
42 var aggregateClass = _aggregateTransformerClass; | |
43 var groupClass = reflectClass(TransformerGroup); | |
44 | |
45 var seen = new Set(); | |
46 var transformers = []; | |
47 | |
48 loadFromLibrary(library) { | |
49 if (seen.contains(library)) return; | |
50 seen.add(library); | |
51 | |
52 // Load transformers from libraries exported by [library]. | |
53 for (var dependency in library.libraryDependencies) { | |
54 if (!dependency.isExport) continue; | |
55 loadFromLibrary(dependency.targetLibrary); | |
56 } | |
57 | |
58 // TODO(nweiz): if no valid transformers are found, throw an error message | |
59 // describing candidates and why they were rejected. | |
60 transformers.addAll(library.declarations.values.map((declaration) { | |
61 if (declaration is! ClassMirror) return null; | |
62 var classMirror = declaration; | |
63 if (classMirror.isPrivate) return null; | |
64 if (classMirror.isAbstract) return null; | |
65 if (!classMirror.isSubtypeOf(transformerClass) && | |
66 !classMirror.isSubtypeOf(groupClass) && | |
67 (aggregateClass == null || | |
68 !classMirror.isSubtypeOf(aggregateClass))) { | |
69 return null; | |
70 } | |
71 | |
72 var constructor = _getConstructor(classMirror, 'asPlugin'); | |
73 if (constructor == null) return null; | |
74 if (constructor.parameters.isEmpty) { | |
75 if (configuration.isNotEmpty) return null; | |
76 return classMirror.newInstance(const Symbol('asPlugin'), []).reflectee; | |
77 } | |
78 if (constructor.parameters.length != 1) return null; | |
79 | |
80 return classMirror.newInstance(const Symbol('asPlugin'), | |
81 [new BarbackSettings(configuration, mode)]).reflectee; | |
82 }).where((classMirror) => classMirror != null)); | |
83 } | |
84 | |
85 var library = _mirrors.libraries[Uri.parse(uri)]; | |
86 | |
87 // This should only happen if something's wrong with the logic in pub itself. | |
88 // If it were user error, the entire isolate would fail to load. | |
89 if (library == null) throw "Couldn't find library at $uri."; | |
90 | |
91 loadFromLibrary(library); | |
92 return transformers; | |
93 } | |
94 | |
95 // TODO(nweiz): clean this up when issue 13248 is fixed. | |
96 MethodMirror _getConstructor(ClassMirror classMirror, String constructor) { | |
97 var name = new Symbol("${MirrorSystem.getName(classMirror.simpleName)}" | |
98 ".$constructor"); | |
99 var candidate = classMirror.declarations[name]; | |
100 if (candidate is MethodMirror && candidate.isConstructor) return candidate; | |
101 return null; | |
102 } | |
103 | |
104 // Older barbacks don't support [AggregateTransformer], and calling | |
105 // [reflectClass] on an undefined class will throw an error, so we just define a | |
106 // null getter for them. | |
107 //# if barback >=0.14.1 | |
108 ClassMirror get _aggregateTransformerClass => | |
109 reflectClass(AggregateTransformer); | |
110 //# else | |
111 //> ClassMirror get _aggregateTransformerClass => null; | |
112 //# end | |
OLD | NEW |