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 85b9ee55a8b728a593bdd5c1e76724b6b3599150..fa3f9cd4316dcd1e1115e6846328360c27e45470 100644 |
--- a/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
+++ b/dart/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart |
@@ -14,10 +14,77 @@ patch class MirrorSystem { |
} |
class _MirrorSystem implements MirrorSystem { |
+ TypeMirror get dynamicType => _dynamicType; |
+ TypeMirror get voidType => _voidType; |
+ |
+ final static TypeMirror _dynamicType = |
+ new _TypeMirror(const Symbol('dynamic')); |
+ final static TypeMirror _voidType = new _TypeMirror(const Symbol('void')); |
+ |
+ static final Map<String, List<LibraryMirror>> librariesByName = |
+ computeLibrariesByName(); |
+ |
+ Iterable<LibraryMirror> findLibrary(Symbol libraryName) { |
+ return new List<LibraryMirror>.from(librariesByName[_n(libraryName)]); |
+ } |
+ |
+ static Map<String, List<LibraryMirror>> computeLibrariesByName() { |
+ var result = new Map<String, List<LibraryMirror>>(); |
+ var jsLibraries = JS('=List|Null', 'init.libraries'); |
+ if (jsLibraries == null) return result; |
+ for (List data in jsLibraries) { |
+ String name = data[0]; |
+ Uri uri = Uri.parse(data[1]); |
+ List<String> classes = data[2]; |
+ List<String> functions = data[3]; |
+ var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]); |
+ libraries.add(new _LibraryMirror(name, uri, classes, functions)); |
+ } |
+ return result; |
+ } |
+} |
+ |
+class _TypeMirror implements TypeMirror { |
+ final Symbol simpleName; |
+ _TypeMirror(this.simpleName); |
+} |
+ |
+class _LibraryMirror extends _ObjectMirror implements LibraryMirror { |
+ final String _name; |
+ final Uri uri; |
+ final List<String> _classes; |
+ final List<String> _functions; |
+ |
+ _LibraryMirror(this._name, this.uri, this._classes, this._functions); |
+ |
+ Map<Symbol, ClassMirror> get classes { |
+ var result = new Map<Symbol, ClassMirror>(); |
+ for (int i = 0; i < _classes.length; i += 2) { |
+ Symbol symbol = _s(_classes[i]); |
+ result[symbol] = _reflectClass(symbol, _classes[i + 1]); |
+ } |
+ return result; |
+ } |
+ |
+ InstanceMirror setField(Symbol fieldName, Object arg) { |
+ // TODO(ahe): This is extremely dangerous!!! |
+ JS('void', r'$[#] = #', _n(fieldName), arg); |
+ return new _InstanceMirror(arg); |
+ } |
+ |
+ InstanceMirror getField(Symbol fieldName) { |
+ // TODO(ahe): This is extremely dangerous!!! |
+ return new _InstanceMirror(JS('', r'$[#]', _n(fieldName))); |
+ } |
} |
String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); |
+Symbol _s(String name) { |
+ if (name == null) return null; |
+ return new _symbol_dev.Symbol.unvalidated(name); |
+} |
+ |
patch MirrorSystem currentMirrorSystem() => _currentMirrorSystem; |
final _MirrorSystem _currentMirrorSystem = new _MirrorSystem(); |
@@ -32,11 +99,13 @@ patch InstanceMirror reflect(Object reflectee) { |
final Expando<ClassMirror> _classMirrors = new Expando<ClassMirror>(); |
-patch ClassMirror reflectClass(Type key) => _reflectClass(key); |
+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'; |
+ClassMirror __reflectClass(Type key) => _reflectClass(_s('$key'), null); |
+ |
+ClassMirror _reflectClass(Symbol symbol, String fields) { |
+ String className = _n(symbol); |
var constructor = Primitives.getConstructor(className); |
if (constructor == null) { |
// Probably an intercepted class. |
@@ -45,13 +114,23 @@ ClassMirror _reflectClass(Type key) { |
} |
var mirror = _classMirrors[constructor]; |
if (mirror == null) { |
- mirror = new _ClassMirror(className, constructor); |
+ mirror = new _ClassMirror(symbol, constructor, fields); |
_classMirrors[constructor] = mirror; |
} |
return mirror; |
} |
-class _InstanceMirror extends InstanceMirror { |
+abstract class _ObjectMirror implements ObjectMirror { |
+ Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) { |
+ return new Future<InstanceMirror>(() => this.setField(fieldName, value)); |
+ } |
+ |
+ Future<InstanceMirror> getFieldAsync(Symbol fieldName) { |
+ return new Future<InstanceMirror>(() => this.getField(fieldName)); |
+ } |
+} |
+ |
+class _InstanceMirror extends _ObjectMirror implements InstanceMirror { |
final reflectee; |
@@ -59,7 +138,7 @@ class _InstanceMirror extends InstanceMirror { |
bool get hasReflectee => true; |
- ClassMirror get type => _reflectClass(reflectee.runtimeType); |
+ ClassMirror get type => __reflectClass(reflectee.runtimeType); |
Future<InstanceMirror> invokeAsync(Symbol memberName, |
List<Object> positionalArguments, |
@@ -98,10 +177,6 @@ class _InstanceMirror extends InstanceMirror { |
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]); |
@@ -113,10 +188,6 @@ class _InstanceMirror extends InstanceMirror { |
fieldName, JSInvocationMirror.GETTER, 'get\$${_n(fieldName)}', []); |
} |
- Future<InstanceMirror> getFieldAsync(Symbol fieldName) { |
- return new Future<InstanceMirror>(() => getField(fieldName)); |
- } |
- |
delegate(Invocation invocation) { |
return JSInvocationMirror.invokeFromMirror(invocation, reflectee); |
} |
@@ -124,12 +195,71 @@ class _InstanceMirror extends InstanceMirror { |
String toString() => 'InstanceMirror($reflectee)'; |
} |
-class _ClassMirror extends ClassMirror { |
- final String _name; |
+class _ClassMirror extends _ObjectMirror implements ClassMirror { |
+ final Symbol simpleName; |
final _jsConstructor; |
+ final String _fields; |
- _ClassMirror(this._name, this._jsConstructor) { |
+ _ClassMirror(this.simpleName, this._jsConstructor, this._fields); |
+ |
+ Map<Symbol, Mirror> get members { |
+ var result = new Map<Symbol, Mirror>(); |
+ var s = _fields.split(";"); |
+ var fields = s[1] == "" ? [] : s[1].split(","); |
+ for (String field in fields) { |
+ _VariableMirror mirror = new _VariableMirror.from(field); |
+ result[mirror.simpleName] = mirror; |
+ } |
+ return result; |
} |
- String toString() => 'ClassMirror($_name)'; |
+ InstanceMirror setField(Symbol fieldName, Object arg) { |
+ // TODO(ahe): This is extremely dangerous!!! |
+ JS('void', r'$[#] = #', '${_n(simpleName)}_${_n(fieldName)}', arg); |
+ return new _InstanceMirror(arg); |
+ } |
+ |
+ InstanceMirror getField(Symbol fieldName) { |
+ // TODO(ahe): This is extremely dangerous!!! |
+ return new _InstanceMirror( |
+ JS('', r'$[#]', '${_n(simpleName)}_${_n(fieldName)}')); |
+ } |
+ |
+ String toString() => 'ClassMirror(${_n(simpleName)})'; |
+} |
+ |
+class _VariableMirror implements VariableMirror { |
+ final Symbol simpleName; |
+ final String _jsName; |
+ final bool _readOnly; |
+ |
+ _VariableMirror(this.simpleName, this._jsName, this._readOnly); |
+ |
+ factory _VariableMirror.from(String descriptor) { |
+ int length = descriptor.length; |
+ var code = fieldCode(descriptor.codeUnitAt(length - 1)); |
+ if (code == 0) { |
+ throw new RuntimeError('Bad field descriptor: $descriptor'); |
+ } |
+ bool hasGetter = (code & 3) != 0; |
+ bool hasSetter = (code >> 2) != 0; |
+ String jsName; |
+ String accessorName = jsName = descriptor.substring(0, length - 1); |
+ int divider = descriptor.indexOf(":"); |
+ if (divider > 0) { |
+ accessorName = accessorName.substring(0, divider); |
+ jsName = accessorName.substring(divider + 1); |
+ } |
+ bool readOnly = hasSetter; |
Johnni Winther
2013/05/23 20:21:59
Shouldn't it be [: readOnly = !hasSetter :] ?
ahe
2013/05/24 12:00:13
Fixed in CL 15895002.
|
+ return new _VariableMirror(_s(accessorName), jsName, readOnly); |
+ } |
+ |
+ TypeMirror get type => _MirrorSystem._dynamicType; |
+ |
+ static int fieldCode(int code) { |
+ if (code >= 60 && code <= 64) return code - 59; |
+ if (code >= 123 && code <= 126) return code - 117; |
+ if (code >= 37 && code <= 43) return code - 27; |
+ return 0; |
+ } |
} |