Chromium Code Reviews| Index: runtime/lib/mirrors_impl.dart |
| =================================================================== |
| --- runtime/lib/mirrors_impl.dart (revision 8354) |
| +++ runtime/lib/mirrors_impl.dart (working copy) |
| @@ -12,16 +12,22 @@ |
| abstract class _LocalMirrorImpl implements Mirror { |
| // Local mirrors always return the same IsolateMirror. This field |
| // is more interesting once we implement remote mirrors. |
| - IsolateMirror get isolate() { return Mirrors.localIsolateMirror(); } |
| + IsolateMirror get isolate() { return _Mirrors.currentIsolateMirror(); } |
| } |
| class _LocalIsolateMirrorImpl extends _LocalMirrorImpl |
| implements IsolateMirror { |
| - _LocalIsolateMirrorImpl(this.debugName, this.rootLibrary, this.libraries) {} |
| + _LocalIsolateMirrorImpl(this.debugName, this.rootLibrary, this._libraries) {} |
| final String debugName; |
| final LibraryMirror rootLibrary; |
| - final Map<String, LibraryMirror> libraries; |
| + final Map<String, LibraryMirror> _libraries; |
| + |
| + Map<String, LibraryMirror> libraries() { return _libraries; } |
| + |
| + String toString() { |
| + return "IsolateMirror on '$debugName'"; |
| + } |
| } |
| // A VMReference is used to hold a reference to a VM-internal object, |
| @@ -53,17 +59,22 @@ |
| for (int i = 0; i < positionalArguments.length; i++) { |
| var arg = positionalArguments[i]; |
| if (arg is Mirror) { |
| + if (arg is! InstanceMirror) { |
| + throw new MirrorException( |
| + 'positional argument $i ($arg) was not an InstanceMirror'); |
| + } |
| + } else if (!isSimpleValue(arg)) { |
| throw new MirrorException( |
| - 'positional argument $i ($arg) was not an InstanceMirror'); |
| - } |
| - if (!isSimpleValue(arg)) { |
| - throw new MirrorException( |
| 'positional argument $i ($arg) was not a simple value'); |
| } |
| } |
| Completer<InstanceMirror> completer = new Completer<InstanceMirror>(); |
| - completer.complete( |
| - _invoke(this, memberName, positionalArguments)); |
| + try { |
| + completer.complete( |
| + _invoke(this, memberName, positionalArguments)); |
| + } catch (var exception) { |
| + completer.completeException(exception); |
| + } |
| return completer.future; |
| } |
| @@ -71,48 +82,230 @@ |
| native 'LocalObjectMirrorImpl_invoke'; |
| } |
| +// Prints a string as it might appear in dart program text. |
| +// TODO(turnidge): Consider truncating. |
| +String _dartEscape(String str) { |
| + bool isNice(int code) { |
| + return (code >= 32 && code <= 126); |
| + } |
| + |
| + StringBuffer buf = new StringBuffer(); |
| + for (int i = 0; i < str.length; i++) { |
| + var input = str[i]; |
| + String output; |
| + switch (input) { |
| + case "\\" : |
| + output = "\\\\"; |
|
Ivan Posva
2012/06/11 16:45:02
You could also use raw strings here. Then the inpu
turnidge
2012/06/12 20:51:46
Oh, forgot about raw strings. Thanks.
|
| + break; |
| + case "\'" : |
| + output = "\\'"; |
| + break; |
| + case '\n' : |
| + output = '\\n'; |
| + break; |
| + case '\r' : |
| + output = '\\r'; |
| + break; |
| + case '\f' : |
| + output = '\\f'; |
| + break; |
| + case '\b' : |
| + output = '\\b'; |
| + break; |
| + case '\t' : |
| + output = '\\t'; |
| + break; |
| + case '\v' : |
| + output = '\\v'; |
| + break; |
| + default: |
| + int code = input.charCodeAt(0); |
| + if (isNice(code)) { |
| + output = input; |
| + } else { |
| + output = '\\u{${code.toRadixString(16)}}'; |
| + } |
| + break; |
| + } |
| + buf.add(output); |
| + } |
| + return buf.toString(); |
| +} |
| + |
| class _LocalInstanceMirrorImpl extends _LocalObjectMirrorImpl |
| implements InstanceMirror { |
| - _LocalInstanceMirrorImpl(ref, this.simpleValue) : super(ref) {} |
| + _LocalInstanceMirrorImpl(ref, |
| + this._class, |
| + this.hasSimpleValue, |
| + this._simpleValue) : super(ref) {} |
| - final simpleValue; |
| + var _class; |
| + InterfaceMirror getClass() { |
| + if (_class is _LazyInterfaceMirror) { |
| + _class = _class.resolve(isolate); |
| + } |
| + return _class; |
| + } |
| + |
| + bool hasSimpleValue; |
| + |
| + var _simpleValue; |
| + get simpleValue() { |
| + if (!hasSimpleValue) { |
| + throw new MirrorException( |
| + "Before accesing simpleValue you must check that hasSimpleValue " |
| + "is true"); |
| + } |
| + return _simpleValue; |
| + } |
| + |
| + String toString() { |
| + if (hasSimpleValue) { |
| + if (simpleValue is String) { |
| + return "InstanceMirror on <'${_dartEscape(simpleValue)}'>"; |
| + } else { |
| + return "InstanceMirror on <$simpleValue>"; |
| + } |
| + } else { |
| + return "InstanceMirror on instance of '${getClass().simpleName}'"; |
| + } |
| + } |
| } |
| +class _LazyInterfaceMirror { |
| + _LazyInterfaceMirror(this.libraryName, this.interfaceName) {} |
| + |
| + InterfaceMirror resolve(IsolateMirror isolate) { |
| + return isolate.libraries()[libraryName].members()[interfaceName]; |
| + } |
| + |
| + final String libraryName; |
| + final String interfaceName; |
| +} |
| + |
| +class _LocalInterfaceMirrorImpl extends _LocalObjectMirrorImpl |
| + implements InterfaceMirror { |
| + _LocalInterfaceMirrorImpl(ref, |
| + this.simpleName, |
| + this.isClass, |
| + this._library, |
| + this._superclass, |
| + this._superinterfaces, |
| + this._defaultFactory) : super(ref) {} |
| + |
| + final String simpleName; |
| + final bool isClass; |
| + |
| + var _library; |
| + LibraryMirror get library() { |
| + if (_library is _LazyLibraryMirror) { |
| + _library = _library.resolve(isolate); |
| + } |
| + return _library; |
| + } |
| + |
| + var _superclass; |
| + InterfaceMirror superclass() { |
|
Ivan Posva
2012/06/11 16:45:02
There seems to a mismatch between getters and meth
turnidge
2012/06/12 20:51:46
I agree that there is a mismatch between getters a
|
| + if (_superclass is _LazyInterfaceMirror) { |
| + _superclass = _superclass.resolve(isolate); |
| + } |
| + return _superclass; |
| + } |
| + |
| + var _superinterfaces; |
| + List<InterfaceMirror> superinterfaces() { |
|
Ivan Posva
2012/06/11 16:45:02
ditto
|
| + if (_superinterfaces.length > 0 && |
| + _superinterfaces[0] is _LazyInterfaceMirror) { |
| + List<InterfaceMirror> resolved = new List<InterfaceMirror>(); |
| + for (int i = 0; i < _superinterfaces.length; i++) { |
| + resolved.add(_superinterfaces[i].resolve(isolate)); |
| + } |
| + _superinterfaces = resolved; |
| + } |
| + return _superinterfaces; |
| + } |
| + |
| + var _defaultFactory; |
| + InterfaceMirror defaultFactory() { |
|
Ivan Posva
2012/06/11 16:45:02
ditto.
|
| + if (_defaultFactory is _LazyInterfaceMirror) { |
| + _defaultFactory = _defaultFactory.resolve(isolate); |
| + } |
| + return _defaultFactory; |
| + } |
| + |
| + String toString() { |
| + return "InterfaceMirror on '$simpleName'"; |
| + } |
| +} |
| + |
| +class _LazyLibraryMirror { |
| + _LazyLibraryMirror(this.libraryName) {} |
| + |
| + LibraryMirror resolve(IsolateMirror isolate) { |
| + return isolate.libraries()[libraryName]; |
| + } |
| + |
| + final String libraryName; |
| +} |
| + |
| class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl |
| implements LibraryMirror { |
| - _LocalLibraryMirrorImpl(ref, this.simpleName, this.url) : super(ref) {} |
| + _LocalLibraryMirrorImpl(ref, |
| + this.simpleName, |
| + this.url, |
| + this._members) : super(ref) {} |
| final String simpleName; |
| final String url; |
| + Map<String, InterfaceMirror> _members; |
| + |
| + Map<String, Mirror> members() { return _members; } |
| + |
| + String toString() { |
| + return "LibraryMirror on '$simpleName'"; |
| + } |
| } |
| class _Mirrors { |
| // Does a port refer to our local isolate? |
| static bool isLocalPort(SendPort port) native 'Mirrors_isLocalPort'; |
| - static IsolateMirror _localIsolateMirror; |
| + static IsolateMirror _currentIsolateMirror = null; |
| + // Creates a new local IsolateMirror. |
| + static IsolateMirror makeLocalIsolateMirror() |
| + native 'Mirrors_makeLocalIsolateMirror'; |
| + |
| // The IsolateMirror for the current isolate. |
| - static IsolateMirror localIsolateMirror() { |
| - if (_localIsolateMirror === null) { |
| - _localIsolateMirror = makeLocalIsolateMirror(); |
| + static IsolateMirror currentIsolateMirror() { |
| + if (_currentIsolateMirror === null) { |
| + _currentIsolateMirror = makeLocalIsolateMirror(); |
| } |
| - return _localIsolateMirror; |
| + return _currentIsolateMirror; |
| } |
| - // Creates a new local IsolateMirror. |
| - static IsolateMirror makeLocalIsolateMirror() |
| - native 'Mirrors_makeLocalIsolateMirror'; |
| - |
| static Future<IsolateMirror> isolateMirrorOf(SendPort port) { |
| Completer<IsolateMirror> completer = new Completer<IsolateMirror>(); |
| if (isLocalPort(port)) { |
| // Make a local isolate mirror. |
| - completer.complete(localIsolateMirror()); |
| + try { |
| + completer.complete(currentIsolateMirror()); |
| + } catch (var exception) { |
| + completer.completeException(exception); |
| + } |
| } else { |
| // Make a remote isolate mirror. |
| throw new NotImplementedException('Remote mirrors not yet implemented'); |
| } |
| return completer.future; |
| } |
| + |
| + // Creates a new local InstanceMirror |
| + static InstanceMirror makeLocalInstanceMirror(Object reflectee) |
| + native 'Mirrors_makeLocalInstanceMirror'; |
| + |
| + // The IsolateMirror for the current isolate. |
| + static InstanceMirror mirrorOf(Object reflectee) { |
| + return makeLocalInstanceMirror(reflectee); |
| + } |
| } |