| Index: dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| diff --git a/dart/sdk/lib/_internal/lib/js_mirrors.dart b/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| index 802ec36be2936060d4a50404c1e7d2077d9d2cde..d54e07c318fd30fb04fb59dfc811eaeeccb146b9 100644
|
| --- a/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| +++ b/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| @@ -71,11 +71,13 @@ class JsMirrorSystem implements MirrorSystem {
|
| List<String> classes = data[2];
|
| List<String> functions = data[3];
|
| var metadataFunction = data[4];
|
| + var fields = data[5];
|
| List metadata = (metadataFunction == null)
|
| ? null : JS('List', '#()', metadataFunction);
|
| var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
|
| libraries.add(
|
| - new JsLibraryMirror(s(name), uri, classes, functions, metadata));
|
| + new JsLibraryMirror(
|
| + s(name), uri, classes, functions, metadata, fields));
|
| }
|
| return result;
|
| }
|
| @@ -84,7 +86,7 @@ class JsMirrorSystem implements MirrorSystem {
|
| IsolateMirror get isolate => throw new UnimplementedError();
|
| }
|
|
|
| -abstract class JsMirror {
|
| +abstract class JsMirror implements Mirror {
|
| const JsMirror();
|
|
|
| abstract String get _prettyName;
|
| @@ -93,6 +95,22 @@ abstract class JsMirror {
|
|
|
| // TODO(ahe): Remove this method from the API.
|
| MirrorSystem get mirrors => currentJsMirrorSystem;
|
| +
|
| + _getField(JsMirror receiver) {
|
| + throw new UnimplementedError();
|
| + }
|
| +
|
| + void _setField(JsMirror receiver, Object arg) {
|
| + throw new UnimplementedError();
|
| + }
|
| +
|
| + _loadField(String name) {
|
| + throw new UnimplementedError();
|
| + }
|
| +
|
| + void _storeField(String name, Object arg) {
|
| + throw new UnimplementedError();
|
| + }
|
| }
|
|
|
| abstract class JsDeclarationMirror extends JsMirror
|
| @@ -109,6 +127,10 @@ abstract class JsDeclarationMirror extends JsMirror
|
|
|
| String toString() => "$_prettyName on '${n(simpleName)}'";
|
|
|
| + List<JsMethodMirror> get _methods {
|
| + throw new RuntimeError('Should not call _methods');
|
| + }
|
| +
|
| // TODO(ahe): Implement this.
|
| SourceLocation get location => throw new UnimplementedError();
|
| }
|
| @@ -134,19 +156,24 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| final List<String> _classes;
|
| final List<String> _functions;
|
| final List _metadata;
|
| + final String _compactFieldSpecification;
|
| List<JsMethodMirror> _cachedFunctionMirrors;
|
| + List<JsVariableMirror> _cachedFields;
|
|
|
| JsLibraryMirror(Symbol simpleName,
|
| - this.uri,
|
| - this._classes,
|
| - this._functions,
|
| - this._metadata)
|
| + this.uri,
|
| + this._classes,
|
| + this._functions,
|
| + this._metadata,
|
| + this._compactFieldSpecification)
|
| : super(simpleName);
|
|
|
| String get _prettyName => 'LibraryMirror';
|
|
|
| Symbol get qualifiedName => simpleName;
|
|
|
| + List<JsMethodMirror> get _methods => _functionMirrors;
|
| +
|
| Map<Symbol, ClassMirror> get classes {
|
| var result = new Map<Symbol, ClassMirror>();
|
| for (String className in _classes) {
|
| @@ -158,14 +185,35 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| }
|
|
|
| InstanceMirror setField(Symbol fieldName, Object arg) {
|
| - // TODO(ahe): This is extremely dangerous!!!
|
| - JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), n(fieldName), arg);
|
| + String name = n(fieldName);
|
| + if (name.endsWith('=')) throw new ArgumentError('');
|
| + var mirror = functions[s('$name=')];
|
| + if (mirror == null) mirror = variables[fieldName];
|
| + if (mirror == null) {
|
| + // TODO(ahe): What receiver to use?
|
| + throw new NoSuchMethodError(this, '${n(fieldName)}=', [arg], null);
|
| + }
|
| + mirror._setField(this, arg);
|
| return reflect(arg);
|
| }
|
|
|
| InstanceMirror getField(Symbol fieldName) {
|
| - // TODO(ahe): This is extremely dangerous!!!
|
| - return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), n(fieldName)));
|
| + JsMirror mirror = members[fieldName];
|
| + if (mirror == null) {
|
| + // TODO(ahe): What receiver to use?
|
| + throw new NoSuchMethodError(this, '${n(fieldName)}', [], null);
|
| + }
|
| + return reflect(mirror._getField(this));
|
| + }
|
| +
|
| + _loadField(String name) {
|
| + assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
|
| + return JS('', '#[#]', JS_CURRENT_ISOLATE(), name);
|
| + }
|
| +
|
| + void _storeField(String name, Object arg) {
|
| + assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
|
| + JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), name, arg);
|
| }
|
|
|
| List<JsMethodMirror> get _functionMirrors {
|
| @@ -193,6 +241,15 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| return _cachedFunctionMirrors = result;
|
| }
|
|
|
| + List<VariableMirror> get _fields {
|
| + if (_cachedFields != null) return _cachedFields;
|
| + var result = <VariableMirror>[];
|
| + parseCompactFieldSpecification(
|
| + this, _compactFieldSpecification, true, result);
|
| + _cachedFields = result;
|
| + return _cachedFields;
|
| + }
|
| +
|
| Map<Symbol, MethodMirror> get functions {
|
| var result = new Map<Symbol, MethodMirror>();
|
| for (JsMethodMirror mirror in _functionMirrors) {
|
| @@ -215,7 +272,9 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
|
|
| Map<Symbol, VariableMirror> get variables {
|
| var result = new Map<Symbol, VariableMirror>();
|
| - // TODO(ahe): Implement this.
|
| + for (JsVariableMirror mirror in _fields) {
|
| + result[mirror.simpleName] = mirror;
|
| + }
|
| return result;
|
| }
|
|
|
| @@ -498,46 +557,19 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| List<VariableMirror> get _fields {
|
| if (_cachedFields != null) return _cachedFields;
|
| var result = <VariableMirror>[];
|
| - var s = _fieldsDescriptor.split(';');
|
| - var fields = s[1] == '' ? [] : s[1].split(',');
|
| - int fieldNumber = 0;
|
| - for (String field in fields) {
|
| - var metadata;
|
| - if (_fieldsMetadata != null) {
|
| - metadata = _fieldsMetadata[fieldNumber++];
|
| - }
|
| - JsVariableMirror mirror =
|
| - new JsVariableMirror.from(field, metadata, this, false);
|
| - if (mirror != null) {
|
| - result.add(mirror);
|
| - }
|
| +
|
| + var instanceFieldSpecfication = _fieldsDescriptor.split(';')[1];
|
| + if (_fieldsMetadata != null) {
|
| + instanceFieldSpecfication =
|
| + [instanceFieldSpecfication]..addAll(_fieldsMetadata);
|
| }
|
| + parseCompactFieldSpecification(
|
| + this, instanceFieldSpecfication, false, result);
|
|
|
| var staticDescriptor = JS('', 'init.statics[#]', _mangledName);
|
| if (staticDescriptor != null) {
|
| - var staticFieldsDescriptor = JS('', '#[""]', staticDescriptor);
|
| - var staticFieldsMetadata = null;
|
| - var staticFields;
|
| - if (staticFieldsDescriptor is List) {
|
| - staticFields = staticFieldsDescriptor[0].split(',');
|
| - staticFieldsMetadata = staticFieldsDescriptor.sublist(1);
|
| - } else if (staticFieldsDescriptor is String) {
|
| - staticFields = staticFieldsDescriptor.split(',');
|
| - } else {
|
| - staticFields = [];
|
| - }
|
| - fieldNumber = 0;
|
| - for (String staticField in staticFields) {
|
| - var metadata;
|
| - if (staticFieldsMetadata != null) {
|
| - metadata = staticFieldsMetadata[fieldNumber++];
|
| - }
|
| - JsVariableMirror mirror =
|
| - new JsVariableMirror.from(staticField, metadata, this, true);
|
| - if (mirror != null) {
|
| - result.add(mirror);
|
| - }
|
| - }
|
| + parseCompactFieldSpecification(
|
| + this, JS('', '#[""]', staticDescriptor), true, result);
|
| }
|
| _cachedFields = result;
|
| return _cachedFields;
|
| @@ -762,7 +794,7 @@ class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
|
|
|
| factory JsVariableMirror.from(String descriptor,
|
| metadataFunction,
|
| - JsClassMirror owner,
|
| + JsDeclarationMirror owner,
|
| bool isStatic) {
|
| int length = descriptor.length;
|
| var code = fieldCode(descriptor.codeUnitAt(length - 1));
|
| @@ -823,6 +855,15 @@ class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
|
| if (code >= 37 && code <= 43) return code - 27;
|
| return 0;
|
| }
|
| +
|
| + _getField(JsMirror receiver) => receiver._loadField(_jsName);
|
| +
|
| + void _setField(JsMirror receiver, Object arg) {
|
| + if (isFinal) {
|
| + throw new NoSuchMethodError(this, '${n(simpleName)}=', [arg], null);
|
| + }
|
| + receiver._storeField(_jsName, arg);
|
| + }
|
| }
|
|
|
| class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
|
| @@ -913,10 +954,10 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
|
| bool isGetter = false;
|
| if (info.length == 1) {
|
| if (isSetter) {
|
| - requiredParameterCount = 2;
|
| + requiredParameterCount = 1;
|
| } else {
|
| isGetter = true;
|
| - requiredParameterCount = 1;
|
| + requiredParameterCount = 0;
|
| }
|
| } else {
|
| requiredParameterCount = int.parse(info[1]);
|
| @@ -987,6 +1028,23 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
|
| new List.from(positionalArguments));
|
| }
|
|
|
| + _getField(JsMirror receiver) {
|
| + if (isGetter) {
|
| + return _invoke([], null);
|
| + } else {
|
| + // TODO(ahe): Closurize method.
|
| + throw new UnimplementedError('getField on $receiver');
|
| + }
|
| + }
|
| +
|
| + _setField(JsMirror receiver, Object arg) {
|
| + if (isSetter) {
|
| + return _invoke([arg], null);
|
| + } else {
|
| + throw new NoSuchMethodError(this, '${n(simpleName)}=', [], null);
|
| + }
|
| + }
|
| +
|
| // TODO(ahe): Implement these.
|
| bool get isAbstract => throw new UnimplementedError();
|
| bool get isRegularMethod => throw new UnimplementedError();
|
| @@ -1053,3 +1111,37 @@ List extractMetadata(victim) {
|
| return source.substring(index, endQuote).split(',').map(int.parse).map(
|
| (int i) => JS('', 'init.metadata[#]', i)).toList();
|
| }
|
| +
|
| +List<JsVariableMirror> parseCompactFieldSpecification(
|
| + JsDeclarationMirror owner,
|
| + fieldSpecification,
|
| + bool isStatic,
|
| + List<Mirror> result) {
|
| + List fieldsMetadata = null;
|
| + List<String> fieldNames;
|
| + if (fieldSpecification is List) {
|
| + fieldNames = splitFields(fieldSpecification[0], ',');
|
| + fieldsMetadata = fieldSpecification.sublist(1);
|
| + } else if (fieldSpecification is String) {
|
| + fieldNames = splitFields(fieldSpecification, ',');
|
| + } else {
|
| + fieldNames = [];
|
| + }
|
| + int fieldNumber = 0;
|
| + for (String field in fieldNames) {
|
| + var metadata;
|
| + if (fieldsMetadata != null) {
|
| + metadata = fieldsMetadata[fieldNumber++];
|
| + }
|
| + var mirror = new JsVariableMirror.from(field, metadata, owner, isStatic);
|
| + if (mirror != null) {
|
| + result.add(mirror);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/// Similar to [String.split], but returns an empty list if [string] is empty.
|
| +List<String> splitFields(String string, Pattern pattern) {
|
| + if (string.isEmpty) return <String>[];
|
| + return string.split(pattern);
|
| +}
|
|
|