Chromium Code Reviews| 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; |
| + } |
| } |