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 // Patch library for dart:mirrors. | 5 // Patch library for dart:mirrors. |
6 | 6 |
7 import 'dart:_foreign_helper' show JS; | 7 import 'dart:_foreign_helper' show JS; |
8 import "dart:_collection-dev" as _symbol_dev; | 8 import 'dart:_collection-dev' as _symbol_dev; |
9 | 9 import 'dart:_js_helper' show createInvocationMirror; |
10 // Yeah, seriously: mirrors in dart2js are experimental... | 10 import 'dart:_interceptors' show getInterceptor; |
11 const String _MIRROR_OPT_IN_MESSAGE = """ | |
12 | |
13 This program is using an experimental feature called \"mirrors\". As | |
14 currently implemented, mirrors do not work with minification, and will | |
15 cause spurious errors depending on how code was optimized. | |
16 | |
17 The authors of this program are aware of these problems and have | |
18 decided the thrill of using an experimental feature is outweighing the | |
19 risks. Furthermore, the authors of this program understand that | |
20 long-term, to fix the problems mentioned above, mirrors may have | |
21 negative impact on size and performance of Dart programs compiled to | |
22 JavaScript. | |
23 """; | |
24 | |
25 bool _mirrorsEnabled = false; | |
26 | 11 |
27 patch class MirrorSystem { | 12 patch class MirrorSystem { |
28 patch static String getName(Symbol symbol) { | 13 patch static String getName(Symbol symbol) => _n(symbol); |
29 return _symbol_dev.Symbol.getName(symbol); | |
30 } | |
31 } | 14 } |
32 | 15 |
33 /** | 16 class _MirrorSystem implements MirrorSystem { |
34 * Stub class for the mirror system. | |
35 */ | |
36 patch MirrorSystem currentMirrorSystem() { | |
37 _ensureEnabled(); | |
38 throw new UnsupportedError("MirrorSystem not implemented"); | |
39 } | 17 } |
40 | 18 |
19 String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); | |
20 | |
21 patch MirrorSystem currentMirrorSystem() => _currentMirrorSystem; | |
22 | |
23 _MirrorSystem _currentMirrorSystem = new _MirrorSystem(); | |
24 | |
41 patch Future<MirrorSystem> mirrorSystemOf(SendPort port) { | 25 patch Future<MirrorSystem> mirrorSystemOf(SendPort port) { |
42 _ensureEnabled(); | |
43 throw new UnsupportedError("MirrorSystem not implemented"); | 26 throw new UnsupportedError("MirrorSystem not implemented"); |
44 } | 27 } |
45 | 28 |
46 patch InstanceMirror reflect(Object reflectee) { | 29 patch InstanceMirror reflect(Object reflectee) { |
47 if (!_mirrorsEnabled && (_MIRROR_OPT_IN_MESSAGE == reflectee)) { | |
48 // Turn on mirrors and warn that it is an experimental feature. | |
49 _mirrorsEnabled = true; | |
50 print(reflectee); | |
51 } | |
52 return new _InstanceMirror(reflectee); | 30 return new _InstanceMirror(reflectee); |
53 } | 31 } |
54 | 32 |
33 Map<String, ClassMirror> _classMirrors = new Map<String, ClassMirror>(); | |
34 | |
55 patch ClassMirror reflectClass(Type key) { | 35 patch ClassMirror reflectClass(Type key) { |
56 throw new UnimplementedError('reflectClass is not yet implemented' | 36 String className = '$key'; |
57 'in dart2js'); | 37 var constructor = Primitives.getConstructor(className); |
38 return _classMirrors.putIfAbsent( | |
39 constructor, () => new _ClassMirror(className, constructor)); | |
ahe
2013/05/07 23:59:12
This isn't right. Restore the expando and figure
| |
58 } | 40 } |
59 | 41 |
60 class _InstanceMirror extends InstanceMirror { | 42 class _InstanceMirror extends InstanceMirror { |
61 static final Expando<ClassMirror> classMirrors = new Expando<ClassMirror>(); | |
62 | 43 |
63 final reflectee; | 44 final reflectee; |
64 | 45 |
65 _InstanceMirror(this.reflectee); | 46 _InstanceMirror(this.reflectee); |
66 | 47 |
67 bool get hasReflectee => true; | 48 bool get hasReflectee => true; |
68 | 49 |
69 ClassMirror get type { | 50 ClassMirror get type => reflectClass(reflectee.runtimeType); |
70 _ensureEnabled(); | 51 |
71 String className = Primitives.objectTypeName(reflectee); | 52 Future<InstanceMirror> invokeAsync(Symbol memberName, |
72 var constructor = Primitives.getConstructor(className); | 53 List<Object> positionalArguments, |
73 var mirror = classMirrors[constructor]; | 54 [Map<String,Object> namedArguments]) { |
74 if (mirror == null) { | 55 if (namedArguments != null && !namedArguments.isEmpty) { |
75 mirror = new _ClassMirror(className, constructor); | 56 throw new UnsupportedError('Named arguments are not implemented'); |
76 classMirrors[constructor] = mirror; | |
77 } | 57 } |
78 return mirror; | 58 return |
59 new Future<InstanceMirror>( | |
60 () => invoke(memberName, positionalArguments, namedArguments)); | |
79 } | 61 } |
80 | 62 |
81 Future<InstanceMirror> invokeAsync(String memberName, | 63 InstanceMirror invoke(Symbol memberName, |
82 List<Object> positionalArguments, | 64 List positionalArguments, |
83 [Map<String,Object> namedArguments]) { | 65 [Map<Symbol,dynamic> namedArguments]) { |
84 _ensureEnabled(); | |
85 if (namedArguments != null && !namedArguments.isEmpty) { | 66 if (namedArguments != null && !namedArguments.isEmpty) { |
86 throw new UnsupportedError('Named arguments are not implemented'); | 67 throw new UnsupportedError('Named arguments are not implemented'); |
87 } | 68 } |
88 // Copy the list to ensure that it can safely be passed to | 69 // Copy the list to ensure that it can safely be passed to |
89 // JavaScript. | 70 // JavaScript. |
90 var jsList = new List.from(positionalArguments); | 71 var jsList = new List.from(positionalArguments); |
91 var mangledName = '${memberName}\$${positionalArguments.length}'; | 72 return _invoke( |
92 var method = JS('var', '#[#]', reflectee, mangledName); | 73 memberName, JSInvocationMirror.METHOD, |
93 var completer = new Completer<InstanceMirror>(); | 74 '${_n(memberName)}\$${positionalArguments.length}', jsList); |
94 // TODO(ahe): [Completer] or [Future] should have API to create a | 75 } |
95 // delayed action. Simulating with a [Timer]. | 76 |
96 Timer.run(() { | 77 InstanceMirror _invoke(Symbol name, |
97 if (JS('String', 'typeof #', method) == 'function') { | 78 int type, |
98 var result = | 79 String mangledName, |
99 JS('var', '#.apply(#, #)', method, reflectee, jsList); | 80 List arguments) { |
100 completer.complete(new _InstanceMirror(result)); | 81 // TODO(ahe): Get the argument names. |
101 } else { | 82 List<String> argumentNames = []; |
102 completer.completeError('not a method $memberName'); | 83 Invocation invocation = createInvocationMirror( |
103 } | 84 _n(name), mangledName, type, arguments, argumentNames); |
104 }); | 85 |
105 return completer.future; | 86 return new _InstanceMirror(delegate(invocation)); |
87 } | |
88 | |
89 Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) { | |
90 return new Future<InstanceMirror>(() => setField(fieldName, value)); | |
91 } | |
92 | |
93 InstanceMirror setField(Symbol fieldName, Object arg) { | |
94 _invoke( | |
95 fieldName, JSInvocationMirror.SETTER, 'set\$${_n(fieldName)}', [arg]); | |
96 return new _InstanceMirror(arg); | |
97 } | |
98 | |
99 InstanceMirror getField(Symbol fieldName) { | |
100 return _invoke( | |
101 fieldName, JSInvocationMirror.GETTER, 'get\$${_n(fieldName)}', []); | |
102 } | |
103 | |
104 Future<InstanceMirror> getFieldAsync(Symbol fieldName) { | |
105 return new Future<InstanceMirror>(() => getField(fieldName)); | |
106 } | 106 } |
107 | 107 |
108 delegate(Invocation invocation) { | 108 delegate(Invocation invocation) { |
109 return JSInvocationMirror.invokeFromMirror(invocation, reflectee); | 109 return JSInvocationMirror.invokeFromMirror(invocation, reflectee); |
110 } | 110 } |
111 | 111 |
112 String toString() => 'InstanceMirror($reflectee)'; | 112 String toString() => 'InstanceMirror($reflectee)'; |
113 } | 113 } |
114 | 114 |
115 class _ClassMirror extends ClassMirror { | 115 class _ClassMirror extends ClassMirror { |
116 final String _name; | 116 final String _name; |
117 final _jsConstructor; | 117 final _jsConstructor; |
118 | 118 |
119 _ClassMirror(this._name, this._jsConstructor) { | 119 _ClassMirror(this._name, this._jsConstructor) { |
120 _ensureEnabled(); | |
121 } | 120 } |
122 | 121 |
123 String toString() => 'ClassMirror($_name)'; | 122 String toString() => 'ClassMirror($_name)'; |
124 } | 123 } |
125 | |
126 _ensureEnabled() { | |
127 if (_mirrorsEnabled) return; | |
128 throw new UnsupportedError('dart:mirrors is an experimental feature'); | |
129 } | |
OLD | NEW |