Index: dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
diff --git a/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart b/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
index dda7d3db3e087d5075e8c1740cc14e0792194f11..85b9ee55a8b728a593bdd5c1e76724b6b3599150 100644 |
--- a/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
+++ b/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
@@ -5,60 +5,53 @@ |
// Patch library for dart:mirrors. |
import 'dart:_foreign_helper' show JS; |
-import "dart:_collection-dev" as _symbol_dev; |
- |
-// Yeah, seriously: mirrors in dart2js are experimental... |
-const String _MIRROR_OPT_IN_MESSAGE = """ |
- |
-This program is using an experimental feature called \"mirrors\". As |
-currently implemented, mirrors do not work with minification, and will |
-cause spurious errors depending on how code was optimized. |
- |
-The authors of this program are aware of these problems and have |
-decided the thrill of using an experimental feature is outweighing the |
-risks. Furthermore, the authors of this program understand that |
-long-term, to fix the problems mentioned above, mirrors may have |
-negative impact on size and performance of Dart programs compiled to |
-JavaScript. |
-"""; |
- |
-bool _mirrorsEnabled = false; |
+import 'dart:_collection-dev' as _symbol_dev; |
+import 'dart:_js_helper' show createInvocationMirror; |
+import 'dart:_interceptors' show getInterceptor; |
patch class MirrorSystem { |
- patch static String getName(Symbol symbol) { |
- return _symbol_dev.Symbol.getName(symbol); |
- } |
+ patch static String getName(Symbol symbol) => _n(symbol); |
} |
-/** |
- * Stub class for the mirror system. |
- */ |
-patch MirrorSystem currentMirrorSystem() { |
- _ensureEnabled(); |
- throw new UnsupportedError("MirrorSystem not implemented"); |
+class _MirrorSystem implements MirrorSystem { |
} |
+String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); |
+ |
+patch MirrorSystem currentMirrorSystem() => _currentMirrorSystem; |
+ |
+final _MirrorSystem _currentMirrorSystem = new _MirrorSystem(); |
+ |
patch Future<MirrorSystem> mirrorSystemOf(SendPort port) { |
- _ensureEnabled(); |
throw new UnsupportedError("MirrorSystem not implemented"); |
} |
patch InstanceMirror reflect(Object reflectee) { |
- if (!_mirrorsEnabled && (_MIRROR_OPT_IN_MESSAGE == reflectee)) { |
- // Turn on mirrors and warn that it is an experimental feature. |
- _mirrorsEnabled = true; |
- print(reflectee); |
- } |
return new _InstanceMirror(reflectee); |
} |
-patch ClassMirror reflectClass(Type key) { |
- throw new UnimplementedError('reflectClass is not yet implemented' |
- 'in dart2js'); |
+final Expando<ClassMirror> _classMirrors = new Expando<ClassMirror>(); |
+ |
+patch ClassMirror reflectClass(Type key) => _reflectClass(key); |
+ |
+// TODO(ahe): This is a workaround for http://dartbug.com/10543 |
+ClassMirror _reflectClass(Type key) { |
+ String className = '$key'; |
+ var constructor = Primitives.getConstructor(className); |
+ if (constructor == null) { |
+ // Probably an intercepted class. |
+ // TODO(ahe): How to handle intercepted classes? |
+ throw new UnsupportedError('Cannot find class for: $className'); |
+ } |
+ var mirror = _classMirrors[constructor]; |
+ if (mirror == null) { |
+ mirror = new _ClassMirror(className, constructor); |
+ _classMirrors[constructor] = mirror; |
+ } |
+ return mirror; |
} |
class _InstanceMirror extends InstanceMirror { |
- static final Expando<ClassMirror> classMirrors = new Expando<ClassMirror>(); |
final reflectee; |
@@ -66,43 +59,62 @@ class _InstanceMirror extends InstanceMirror { |
bool get hasReflectee => true; |
- ClassMirror get type { |
- _ensureEnabled(); |
- String className = Primitives.objectTypeName(reflectee); |
- var constructor = Primitives.getConstructor(className); |
- var mirror = classMirrors[constructor]; |
- if (mirror == null) { |
- mirror = new _ClassMirror(className, constructor); |
- classMirrors[constructor] = mirror; |
- } |
- return mirror; |
- } |
+ ClassMirror get type => _reflectClass(reflectee.runtimeType); |
- Future<InstanceMirror> invokeAsync(String memberName, |
+ Future<InstanceMirror> invokeAsync(Symbol memberName, |
List<Object> positionalArguments, |
[Map<String,Object> namedArguments]) { |
- _ensureEnabled(); |
+ if (namedArguments != null && !namedArguments.isEmpty) { |
+ throw new UnsupportedError('Named arguments are not implemented'); |
+ } |
+ return |
+ new Future<InstanceMirror>( |
+ () => invoke(memberName, positionalArguments, namedArguments)); |
+ } |
+ |
+ InstanceMirror invoke(Symbol memberName, |
+ List positionalArguments, |
+ [Map<Symbol,dynamic> namedArguments]) { |
if (namedArguments != null && !namedArguments.isEmpty) { |
throw new UnsupportedError('Named arguments are not implemented'); |
} |
// Copy the list to ensure that it can safely be passed to |
// JavaScript. |
var jsList = new List.from(positionalArguments); |
- var mangledName = '${memberName}\$${positionalArguments.length}'; |
- var method = JS('var', '#[#]', reflectee, mangledName); |
- var completer = new Completer<InstanceMirror>(); |
- // TODO(ahe): [Completer] or [Future] should have API to create a |
- // delayed action. Simulating with a [Timer]. |
- Timer.run(() { |
- if (JS('String', 'typeof #', method) == 'function') { |
- var result = |
- JS('var', '#.apply(#, #)', method, reflectee, jsList); |
- completer.complete(new _InstanceMirror(result)); |
- } else { |
- completer.completeError('not a method $memberName'); |
- } |
- }); |
- return completer.future; |
+ return _invoke( |
+ memberName, JSInvocationMirror.METHOD, |
+ '${_n(memberName)}\$${positionalArguments.length}', jsList); |
+ } |
+ |
+ InstanceMirror _invoke(Symbol name, |
+ int type, |
+ String mangledName, |
+ List arguments) { |
+ // TODO(ahe): Get the argument names. |
+ List<String> argumentNames = []; |
+ Invocation invocation = createInvocationMirror( |
+ _n(name), mangledName, type, arguments, argumentNames); |
+ |
+ return new _InstanceMirror(delegate(invocation)); |
+ } |
+ |
+ Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) { |
+ return new Future<InstanceMirror>(() => setField(fieldName, value)); |
+ } |
+ |
+ InstanceMirror setField(Symbol fieldName, Object arg) { |
+ _invoke( |
+ fieldName, JSInvocationMirror.SETTER, 'set\$${_n(fieldName)}', [arg]); |
+ return new _InstanceMirror(arg); |
+ } |
+ |
+ InstanceMirror getField(Symbol fieldName) { |
+ return _invoke( |
+ fieldName, JSInvocationMirror.GETTER, 'get\$${_n(fieldName)}', []); |
+ } |
+ |
+ Future<InstanceMirror> getFieldAsync(Symbol fieldName) { |
+ return new Future<InstanceMirror>(() => getField(fieldName)); |
} |
delegate(Invocation invocation) { |
@@ -117,13 +129,7 @@ class _ClassMirror extends ClassMirror { |
final _jsConstructor; |
_ClassMirror(this._name, this._jsConstructor) { |
- _ensureEnabled(); |
} |
String toString() => 'ClassMirror($_name)'; |
} |
- |
-_ensureEnabled() { |
- if (_mirrorsEnabled) return; |
- throw new UnsupportedError('dart:mirrors is an experimental feature'); |
-} |