Chromium Code Reviews| 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 |