| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart._js_mirrors; | 5 library dart._js_mirrors; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection' show UnmodifiableListView; | 8 import 'dart:collection' show UnmodifiableListView; |
| 9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 10 | 10 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 code ^= 17 * simpleName.hashCode; | 200 code ^= 17 * simpleName.hashCode; |
| 201 code ^= 19 * owner.hashCode; | 201 code ^= 19 * owner.hashCode; |
| 202 return code; | 202 return code; |
| 203 } | 203 } |
| 204 | 204 |
| 205 String get _prettyName => 'TypeVariableMirror'; | 205 String get _prettyName => 'TypeVariableMirror'; |
| 206 | 206 |
| 207 TypeMirror get upperBound { | 207 TypeMirror get upperBound { |
| 208 if (_cachedUpperBound != null) return _cachedUpperBound; | 208 if (_cachedUpperBound != null) return _cachedUpperBound; |
| 209 return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation( | 209 return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation( |
| 210 JS('', 'init.metadata[#]', _typeVariable.bound)); | 210 owner, getMetadata(_typeVariable.bound)); |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 | 213 |
| 214 class JsTypeMirror extends JsDeclarationMirror implements TypeMirror { | 214 class JsTypeMirror extends JsDeclarationMirror implements TypeMirror { |
| 215 JsTypeMirror(Symbol simpleName) | 215 JsTypeMirror(Symbol simpleName) |
| 216 : super(simpleName); | 216 : super(simpleName); |
| 217 | 217 |
| 218 String get _prettyName => 'TypeMirror'; | 218 String get _prettyName => 'TypeMirror'; |
| 219 | 219 |
| 220 DeclarationMirror get owner => null; | 220 DeclarationMirror get owner => null; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 // Remove the angle brackets enclosing the type arguments. | 495 // Remove the angle brackets enclosing the type arguments. |
| 496 mangledName.substring(typeArgIndex + 1, mangledName.length - 1)); | 496 mangledName.substring(typeArgIndex + 1, mangledName.length - 1)); |
| 497 JsCache.update(classMirrors, mangledName, mirror); | 497 JsCache.update(classMirrors, mangledName, mirror); |
| 498 return mirror; | 498 return mirror; |
| 499 } | 499 } |
| 500 var constructorOrInterceptor = | 500 var constructorOrInterceptor = |
| 501 Primitives.getConstructorOrInterceptor(mangledName); | 501 Primitives.getConstructorOrInterceptor(mangledName); |
| 502 if (constructorOrInterceptor == null) { | 502 if (constructorOrInterceptor == null) { |
| 503 int index = JS('int|Null', 'init.functionAliases[#]', mangledName); | 503 int index = JS('int|Null', 'init.functionAliases[#]', mangledName); |
| 504 if (index != null) { | 504 if (index != null) { |
| 505 mirror = new JsTypedefMirror( | 505 mirror = new JsTypedefMirror(symbol, mangledName, getMetadata(index)); |
| 506 symbol, mangledName, JS('=Object', 'init.metadata[#]', index)); | |
| 507 JsCache.update(classMirrors, mangledName, mirror); | 506 JsCache.update(classMirrors, mangledName, mirror); |
| 508 return mirror; | 507 return mirror; |
| 509 } | 508 } |
| 510 // Probably an intercepted class. | 509 // Probably an intercepted class. |
| 511 // TODO(ahe): How to handle intercepted classes? | 510 // TODO(ahe): How to handle intercepted classes? |
| 512 throw new UnsupportedError('Cannot find class for: ${n(symbol)}'); | 511 throw new UnsupportedError('Cannot find class for: ${n(symbol)}'); |
| 513 } | 512 } |
| 514 var constructor = (constructorOrInterceptor is Interceptor) | 513 var constructor = (constructorOrInterceptor is Interceptor) |
| 515 ? JS('', '#.constructor', constructorOrInterceptor) | 514 ? JS('', '#.constructor', constructorOrInterceptor) |
| 516 : constructorOrInterceptor; | 515 : constructorOrInterceptor; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 String mangledName = | 740 String mangledName = |
| 742 JS('String|Null', '#[#]', methodsWithOptionalArguments, '*$name'); | 741 JS('String|Null', '#[#]', methodsWithOptionalArguments, '*$name'); |
| 743 if (mangledName == null) { | 742 if (mangledName == null) { |
| 744 // TODO(ahe): Invoke noSuchMethod. | 743 // TODO(ahe): Invoke noSuchMethod. |
| 745 throw new UnimplementedNoSuchMethodError( | 744 throw new UnimplementedNoSuchMethodError( |
| 746 'Invoking noSuchMethod with named arguments not implemented'); | 745 'Invoking noSuchMethod with named arguments not implemented'); |
| 747 } | 746 } |
| 748 var defaultValueIndices = | 747 var defaultValueIndices = |
| 749 JS('List|Null', '#[#].\$defaultValues', reflectee, mangledName); | 748 JS('List|Null', '#[#].\$defaultValues', reflectee, mangledName); |
| 750 var defaultValues = | 749 var defaultValues = |
| 751 defaultValueIndices.map((int i) => JS('', 'init.metadata[#]', i)) | 750 defaultValueIndices.map((int i) => getMetadata(i)) |
| 752 .iterator; | 751 .iterator; |
| 753 var defaultArguments = new Map(); | 752 var defaultArguments = new Map(); |
| 754 reflectiveName = mangledNames[mangledName]; | 753 reflectiveName = mangledNames[mangledName]; |
| 755 var reflectiveNames = reflectiveName.split(':'); | 754 var reflectiveNames = reflectiveName.split(':'); |
| 756 int requiredPositionalArgumentCount = | 755 int requiredPositionalArgumentCount = |
| 757 int.parse(reflectiveNames.elementAt(1)); | 756 int.parse(reflectiveNames.elementAt(1)); |
| 758 positionalArguments = new List.from(positionalArguments); | 757 positionalArguments = new List.from(positionalArguments); |
| 759 // Check the number of positional arguments is valid. | 758 // Check the number of positional arguments is valid. |
| 760 if (requiredPositionalArgumentCount != positionalArguments.length) { | 759 if (requiredPositionalArgumentCount != positionalArguments.length) { |
| 761 // TODO(ahe): Invoke noSuchMethod. | 760 // TODO(ahe): Invoke noSuchMethod. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 * to JsCLassMirror that returns an empty list since it represents original | 874 * to JsCLassMirror that returns an empty list since it represents original |
| 876 * declarations and classes that are not generic. | 875 * declarations and classes that are not generic. |
| 877 */ | 876 */ |
| 878 class JsTypeBoundClassMirror extends JsDeclarationMirror implements ClassMirror
{ | 877 class JsTypeBoundClassMirror extends JsDeclarationMirror implements ClassMirror
{ |
| 879 final JsClassMirror _class; | 878 final JsClassMirror _class; |
| 880 | 879 |
| 881 /** | 880 /** |
| 882 * When instantiated this field will hold a string representing the list of | 881 * When instantiated this field will hold a string representing the list of |
| 883 * type arguments for the class, i.e. what is inside the outermost angle | 882 * type arguments for the class, i.e. what is inside the outermost angle |
| 884 * brackets. Then, when get typeArguments is called the first time, the string | 883 * brackets. Then, when get typeArguments is called the first time, the string |
| 885 * is parsed into the actual list of TypeMirrors, and the field is overridden | 884 * is parsed into the actual list of TypeMirrors, and stored in |
| 886 * with this value. | 885 * [_cachedTypeArguments]. Due to type substitution of for instance |
| 886 * superclasses the mangled name of the class and hence this string is needed |
| 887 * after [_cachedTypeArguments] has been computed. |
| 887 * | 888 * |
| 888 * If an integer is encountered as a type argument, it represents the type | 889 * If an integer is encountered as a type argument, it represents the type |
| 889 * variable at the corresponding entry in [emitter.globalMetadata]. | 890 * variable at the corresponding entry in [emitter.globalMetadata]. |
| 890 */ | 891 */ |
| 891 var _typeArguments; | 892 String _typeArguments; |
| 892 | 893 |
| 894 UnmodifiableListView<TypeMirror> _cachedTypeArguments; |
| 893 Map<Symbol, VariableMirror> _cachedVariables; | 895 Map<Symbol, VariableMirror> _cachedVariables; |
| 894 Map<Symbol, MethodMirror> _cachedGetters; | 896 Map<Symbol, MethodMirror> _cachedGetters; |
| 895 Map<Symbol, MethodMirror> _cachedSetters; | 897 Map<Symbol, MethodMirror> _cachedSetters; |
| 896 Map<Symbol, MethodMirror> _cachedMethodsMap; | 898 Map<Symbol, MethodMirror> _cachedMethodsMap; |
| 897 List<JsMethodMirror> _cachedMethods; | 899 List<JsMethodMirror> _cachedMethods; |
| 900 ClassMirror _superclass; |
| 901 List<ClassMirror> _cachedSuperinterfaces; |
| 898 | 902 |
| 899 JsTypeBoundClassMirror(JsClassMirror originalDeclaration, this._typeArguments) | 903 JsTypeBoundClassMirror(JsClassMirror originalDeclaration, this._typeArguments) |
| 900 : _class = originalDeclaration, | 904 : _class = originalDeclaration, |
| 901 super(originalDeclaration.simpleName); | 905 super(originalDeclaration.simpleName); |
| 902 | 906 |
| 903 String get _prettyName => 'ClassMirror'; | 907 String get _prettyName => 'ClassMirror'; |
| 904 | 908 String get _mangledName => '${_class._mangledName}<$_typeArguments>'; |
| 909 |
| 905 List<TypeVariableMirror> get typeVariables => _class.typeVariables; | 910 List<TypeVariableMirror> get typeVariables => _class.typeVariables; |
| 906 | 911 |
| 907 List<TypeMirror> get typeArguments { | 912 List<TypeMirror> get typeArguments { |
| 908 if (_typeArguments is! String) return _typeArguments; | 913 if (_cachedTypeArguments != null) return _cachedTypeArguments; |
| 909 List result = new List(); | 914 List result = new List(); |
| 910 | 915 |
| 911 addTypeArgument(String typeArgument) { | 916 addTypeArgument(String typeArgument) { |
| 912 int parsedIndex = int.parse(typeArgument, onError: (_) => -1); | 917 int parsedIndex = int.parse(typeArgument, onError: (_) => -1); |
| 913 if (parsedIndex == -1) { | 918 if (parsedIndex == -1) { |
| 914 result.add(reflectClassByMangledName(typeArgument.trim())); | 919 result.add(reflectClassByMangledName(typeArgument.trim())); |
| 915 } else { | 920 } else { |
| 916 TypeVariable typeVariable = JS('', 'init.metadata[#]', parsedIndex); | 921 TypeVariable typeVariable = getMetadata(parsedIndex); |
| 917 TypeMirror owner = reflectClass(typeVariable.owner); | 922 TypeMirror owner = reflectClass(typeVariable.owner); |
| 918 TypeVariableMirror typeMirror = | 923 TypeVariableMirror typeMirror = |
| 919 new JsTypeVariableMirror(typeVariable, owner); | 924 new JsTypeVariableMirror(typeVariable, owner); |
| 920 result.add(typeMirror); | 925 result.add(typeMirror); |
| 921 } | 926 } |
| 922 } | 927 } |
| 923 | 928 |
| 924 if (_typeArguments.indexOf('<') == -1) { | 929 if (_typeArguments.indexOf('<') == -1) { |
| 925 _typeArguments.split(',').forEach((t) => addTypeArgument(t)); | 930 _typeArguments.split(',').forEach((t) => addTypeArgument(t)); |
| 926 } else { | 931 } else { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 943 } else { | 948 } else { |
| 944 addTypeArgument(currentTypeArgument); | 949 addTypeArgument(currentTypeArgument); |
| 945 currentTypeArgument = ''; | 950 currentTypeArgument = ''; |
| 946 } | 951 } |
| 947 } else { | 952 } else { |
| 948 currentTypeArgument += character; | 953 currentTypeArgument += character; |
| 949 } | 954 } |
| 950 } | 955 } |
| 951 addTypeArgument(currentTypeArgument); | 956 addTypeArgument(currentTypeArgument); |
| 952 } | 957 } |
| 953 return _typeArguments = new UnmodifiableListView(result); | 958 return _cachedTypeArguments = new UnmodifiableListView(result); |
| 954 } | 959 } |
| 955 | 960 |
| 956 Map<Symbol, MethodMirror> get constructors => _class.constructors; | 961 Map<Symbol, MethodMirror> get constructors => _class.constructors; |
| 957 | 962 |
| 958 List<JsMethodMirror> get _methods { | 963 List<JsMethodMirror> get _methods { |
| 959 if (_cachedMethods != null) return _cachedMethods; | 964 if (_cachedMethods != null) return _cachedMethods; |
| 960 return _cachedMethods =_class._getMethodsWithOwner(this); | 965 return _cachedMethods =_class._getMethodsWithOwner(this); |
| 961 } | 966 } |
| 962 | 967 |
| 963 Map<Symbol, MethodMirror> get methods { | 968 Map<Symbol, MethodMirror> get methods { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 [Map<Symbol, dynamic> namedArguments]) { | 1015 [Map<Symbol, dynamic> namedArguments]) { |
| 1011 return _class.newInstanceAsync(constructorName, | 1016 return _class.newInstanceAsync(constructorName, |
| 1012 positionalArguments, | 1017 positionalArguments, |
| 1013 namedArguments); | 1018 namedArguments); |
| 1014 } | 1019 } |
| 1015 | 1020 |
| 1016 JsLibraryMirror get owner => _class.owner; | 1021 JsLibraryMirror get owner => _class.owner; |
| 1017 | 1022 |
| 1018 List<InstanceMirror> get metadata => _class.metadata; | 1023 List<InstanceMirror> get metadata => _class.metadata; |
| 1019 | 1024 |
| 1020 ClassMirror get superclass => _class.superclass; | 1025 ClassMirror get superclass { |
| 1026 if (_superclass != null) return _superclass; |
| 1027 |
| 1028 List<int> typeInformation = |
| 1029 JS('List|Null', 'init.typeInformation[#]', _class._mangledName); |
| 1030 assert(typeInformation != null); |
| 1031 var type = getMetadata(typeInformation[0]); |
| 1032 return _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type); |
| 1033 } |
| 1021 | 1034 |
| 1022 InstanceMirror invoke(Symbol memberName, | 1035 InstanceMirror invoke(Symbol memberName, |
| 1023 List positionalArguments, | 1036 List positionalArguments, |
| 1024 [Map<Symbol,dynamic> namedArguments]) { | 1037 [Map<Symbol,dynamic> namedArguments]) { |
| 1025 return _class.invoke(memberName, positionalArguments, namedArguments); | 1038 return _class.invoke(memberName, positionalArguments, namedArguments); |
| 1026 } | 1039 } |
| 1027 | 1040 |
| 1028 bool get isOriginalDeclaration => false; | 1041 bool get isOriginalDeclaration => false; |
| 1029 | 1042 |
| 1030 ClassMirror get originalDeclaration => _class; | 1043 ClassMirror get originalDeclaration => _class; |
| 1031 | 1044 |
| 1032 List<ClassMirror> get superinterfaces => _class.superinterfaces; | 1045 List<ClassMirror> get superinterfaces { |
| 1046 if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces; |
| 1047 return _cachedSuperinterfaces = _class._getSuperinterfacesWithOwner(this); |
| 1048 } |
| 1033 | 1049 |
| 1034 Future<InstanceMirror> getFieldAsync(Symbol fieldName) { | 1050 Future<InstanceMirror> getFieldAsync(Symbol fieldName) { |
| 1035 return _class.getFieldAsync(fieldName); | 1051 return _class.getFieldAsync(fieldName); |
| 1036 } | 1052 } |
| 1037 | 1053 |
| 1038 bool get hasReflectedType => _class.hasReflectedType; | 1054 bool get hasReflectedType => _class.hasReflectedType; |
| 1039 | 1055 |
| 1040 Future<InstanceMirror> invokeAsync(Symbol memberName, | 1056 Future<InstanceMirror> invokeAsync(Symbol memberName, |
| 1041 List positionalArguments, | 1057 List positionalArguments, |
| 1042 [Map<Symbol, dynamic> namedArguments]) { | 1058 [Map<Symbol, dynamic> namedArguments]) { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 if (_cachedMetadata != null) return _cachedMetadata; | 1366 if (_cachedMetadata != null) return _cachedMetadata; |
| 1351 if (_metadata == null) { | 1367 if (_metadata == null) { |
| 1352 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); | 1368 _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); |
| 1353 } | 1369 } |
| 1354 return _cachedMetadata = | 1370 return _cachedMetadata = |
| 1355 new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect)); | 1371 new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect)); |
| 1356 } | 1372 } |
| 1357 | 1373 |
| 1358 ClassMirror get superclass { | 1374 ClassMirror get superclass { |
| 1359 if (_superclass == null) { | 1375 if (_superclass == null) { |
| 1360 var superclassName = _fieldsDescriptor.split(';')[0]; | 1376 List<int> typeInformation = |
| 1361 var mixins = superclassName.split('+'); | 1377 JS('List|Null', 'init.typeInformation[#]', _mangledName); |
| 1362 if (mixins.length > 1) { | 1378 if (typeInformation != null) { |
| 1363 if (mixins.length != 2) { | 1379 var type = getMetadata(typeInformation[0]); |
| 1364 throw new RuntimeError('Strange mixin: $_fieldsDescriptor'); | 1380 _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type); |
| 1381 } else { |
| 1382 var superclassName = _fieldsDescriptor.split(';')[0]; |
| 1383 // TODO(zarah): Remove special handing of mixins. |
| 1384 var mixins = superclassName.split('+'); |
| 1385 if (mixins.length > 1) { |
| 1386 if (mixins.length != 2) { |
| 1387 throw new RuntimeError('Strange mixin: $_fieldsDescriptor'); |
| 1388 } |
| 1389 _superclass = reflectClassByMangledName(mixins[0]); |
| 1390 } else { |
| 1391 // Use _superclass == this to represent class with no superclass |
| 1392 // (Object). |
| 1393 _superclass = (superclassName == '') |
| 1394 ? this : reflectClassByMangledName(superclassName); |
| 1395 } |
| 1365 } | 1396 } |
| 1366 _superclass = reflectClassByMangledName(mixins[0]); | |
| 1367 } else { | |
| 1368 // Use _superclass == this to represent class with no superclass (Object
). | |
| 1369 _superclass = (superclassName == '') | |
| 1370 ? this : reflectClassByMangledName(superclassName); | |
| 1371 } | 1397 } |
| 1372 } | |
| 1373 return _superclass == this ? null : _superclass; | 1398 return _superclass == this ? null : _superclass; |
| 1374 } | 1399 } |
| 1375 | 1400 |
| 1376 InstanceMirror invoke(Symbol memberName, | 1401 InstanceMirror invoke(Symbol memberName, |
| 1377 List positionalArguments, | 1402 List positionalArguments, |
| 1378 [Map<Symbol,dynamic> namedArguments]) { | 1403 [Map<Symbol,dynamic> namedArguments]) { |
| 1379 // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a | 1404 // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a |
| 1380 // static method. | 1405 // static method. |
| 1381 | 1406 |
| 1382 if (namedArguments != null && !namedArguments.isEmpty) { | 1407 if (namedArguments != null && !namedArguments.isEmpty) { |
| 1383 throw new UnsupportedError('Named arguments are not implemented.'); | 1408 throw new UnsupportedError('Named arguments are not implemented.'); |
| 1384 } | 1409 } |
| 1385 JsMethodMirror mirror = methods[memberName]; | 1410 JsMethodMirror mirror = methods[memberName]; |
| 1386 if (mirror == null || !mirror.isStatic) { | 1411 if (mirror == null || !mirror.isStatic) { |
| 1387 // TODO(ahe): What receiver to use? | 1412 // TODO(ahe): What receiver to use? |
| 1388 throw new NoSuchMethodError( | 1413 throw new NoSuchMethodError( |
| 1389 this, memberName, positionalArguments, namedArguments); | 1414 this, memberName, positionalArguments, namedArguments); |
| 1390 } | 1415 } |
| 1391 if (!mirror.canInvokeReflectively()) { | 1416 if (!mirror.canInvokeReflectively()) { |
| 1392 throwInvalidReflectionError(n(memberName)); | 1417 throwInvalidReflectionError(n(memberName)); |
| 1393 } | 1418 } |
| 1394 return reflect(mirror._invoke(positionalArguments, namedArguments)); | 1419 return reflect(mirror._invoke(positionalArguments, namedArguments)); |
| 1395 } | 1420 } |
| 1396 | 1421 |
| 1397 bool get isOriginalDeclaration => true; | 1422 bool get isOriginalDeclaration => true; |
| 1398 | 1423 |
| 1399 ClassMirror get originalDeclaration => this; | 1424 ClassMirror get originalDeclaration => this; |
| 1400 | 1425 |
| 1426 List<ClassMirror> _getSuperinterfacesWithOwner(DeclarationMirror owner) { |
| 1427 List<int> typeInformation = |
| 1428 JS('List|Null', 'init.typeInformation[#]', _mangledName); |
| 1429 List<ClassMirror> result = const <ClassMirror>[]; |
| 1430 if (typeInformation != null) { |
| 1431 ClassMirror lookupType(int i) { |
| 1432 var type = getMetadata(i); |
| 1433 return typeMirrorFromRuntimeTypeRepresentation(owner, type); |
| 1434 } |
| 1435 |
| 1436 //We skip the first since it is the supertype. |
| 1437 result = typeInformation.skip(1).map(lookupType).toList(); |
| 1438 } |
| 1439 |
| 1440 return new UnmodifiableListView<ClassMirror>(result); |
| 1441 } |
| 1442 |
| 1401 List<ClassMirror> get superinterfaces { | 1443 List<ClassMirror> get superinterfaces { |
| 1402 if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces; | 1444 if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces; |
| 1403 List<int> interfaces = JS('List|Null', 'init.interfaces[#]', _mangledName); | 1445 return _cachedSuperinterfaces = _getSuperinterfacesWithOwner(this); |
| 1404 var result = const []; | |
| 1405 if (interfaces != null) { | |
| 1406 ClassMirror lookupType(int i) { | |
| 1407 var type = JS('=Object', 'init.metadata[#]', i); | |
| 1408 return typeMirrorFromRuntimeTypeRepresentation(type); | |
| 1409 } | |
| 1410 result = interfaces.map(lookupType).toList(); | |
| 1411 } | |
| 1412 return _cachedSuperinterfaces = | |
| 1413 new UnmodifiableListView<ClassMirror>(result); | |
| 1414 } | 1446 } |
| 1415 | 1447 |
| 1416 List<TypeVariableMirror> get typeVariables { | 1448 List<TypeVariableMirror> get typeVariables { |
| 1417 if (_cachedTypeVariables != null) return _cachedTypeVariables; | 1449 if (_cachedTypeVariables != null) return _cachedTypeVariables; |
| 1418 List result = new List(); | 1450 List result = new List(); |
| 1419 List typeVariables = | 1451 List typeVariables = |
| 1420 JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor); | 1452 JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor); |
| 1421 if (typeVariables == null) return result; | 1453 if (typeVariables == null) return result; |
| 1422 for (int i = 0; i < typeVariables.length; i++) { | 1454 for (int i = 0; i < typeVariables.length; i++) { |
| 1423 TypeVariable typeVariable = JS('', 'init.metadata[#]', typeVariables[i]); | 1455 TypeVariable typeVariable = getMetadata(typeVariables[i]); |
| 1424 result.add(new JsTypeVariableMirror(typeVariable, this)); | 1456 result.add(new JsTypeVariableMirror(typeVariable, this)); |
| 1425 } | 1457 } |
| 1426 return _cachedTypeVariables = new UnmodifiableListView(result); | 1458 return _cachedTypeVariables = new UnmodifiableListView(result); |
| 1427 } | 1459 } |
| 1428 | 1460 |
| 1429 List<TypeMirror> get typeArguments => const <TypeMirror>[]; | 1461 List<TypeMirror> get typeArguments => const <TypeMirror>[]; |
| 1430 } | 1462 } |
| 1431 | 1463 |
| 1432 class JsVariableMirror extends JsDeclarationMirror implements VariableMirror { | 1464 class JsVariableMirror extends JsDeclarationMirror implements VariableMirror { |
| 1433 static final int REFLECTION_MARKER = 45; | 1465 static final int REFLECTION_MARKER = 45; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1656 } | 1688 } |
| 1657 | 1689 |
| 1658 bool canInvokeReflectively() { | 1690 bool canInvokeReflectively() { |
| 1659 return hasReflectableProperty(_jsFunction); | 1691 return hasReflectableProperty(_jsFunction); |
| 1660 } | 1692 } |
| 1661 | 1693 |
| 1662 DeclarationMirror get owner => _owner; | 1694 DeclarationMirror get owner => _owner; |
| 1663 | 1695 |
| 1664 TypeMirror get returnType { | 1696 TypeMirror get returnType { |
| 1665 metadata; // Compute _returnType as a side-effect of extracting metadata. | 1697 metadata; // Compute _returnType as a side-effect of extracting metadata. |
| 1666 return computeTypeMirror(owner, _returnType); | 1698 return typeMirrorFromRuntimeTypeRepresentation(owner, _returnType); |
| 1667 } | 1699 } |
| 1668 | 1700 |
| 1669 List<InstanceMirror> get metadata { | 1701 List<InstanceMirror> get metadata { |
| 1670 if (_metadata == null) { | 1702 if (_metadata == null) { |
| 1671 var raw = extractMetadata(_jsFunction); | 1703 var raw = extractMetadata(_jsFunction); |
| 1672 var formals = new List(_parameterCount); | 1704 var formals = new List(_parameterCount); |
| 1673 if (!raw.isEmpty) { | 1705 if (!raw.isEmpty) { |
| 1674 _returnType = raw[0]; | 1706 _returnType = raw[0]; |
| 1675 int parameterLength = 1 + _parameterCount * 2; | 1707 int parameterLength = 1 + _parameterCount * 2; |
| 1676 int formalsCount = 0; | 1708 int formalsCount = 0; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 final DeclarationMirror owner; | 1787 final DeclarationMirror owner; |
| 1756 // A JS object representing the type. | 1788 // A JS object representing the type. |
| 1757 final _type; | 1789 final _type; |
| 1758 | 1790 |
| 1759 JsParameterMirror(String unmangledName, this.owner, this._type) | 1791 JsParameterMirror(String unmangledName, this.owner, this._type) |
| 1760 : super(s(unmangledName)); | 1792 : super(s(unmangledName)); |
| 1761 | 1793 |
| 1762 String get _prettyName => 'ParameterMirror'; | 1794 String get _prettyName => 'ParameterMirror'; |
| 1763 | 1795 |
| 1764 TypeMirror get type { | 1796 TypeMirror get type { |
| 1765 return computeTypeMirror(owner, _type); | 1797 return typeMirrorFromRuntimeTypeRepresentation(owner, _type); |
| 1766 } | 1798 } |
| 1767 | 1799 |
| 1768 // Only true for static fields, never for a parameter. | 1800 // Only true for static fields, never for a parameter. |
| 1769 bool get isStatic => false; | 1801 bool get isStatic => false; |
| 1770 | 1802 |
| 1771 // TODO(ahe): Implement this. | 1803 // TODO(ahe): Implement this. |
| 1772 bool get isFinal => false; | 1804 bool get isFinal => false; |
| 1773 | 1805 |
| 1774 // TODO(ahe): Implement this. | 1806 // TODO(ahe): Implement this. |
| 1775 bool get isOptional => false; | 1807 bool get isOptional => false; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 bool get _isVoid => JS('bool', '!!#.void', _typeData); | 1848 bool get _isVoid => JS('bool', '!!#.void', _typeData); |
| 1817 | 1849 |
| 1818 bool get _hasArguments => JS('bool', '"args" in #', _typeData); | 1850 bool get _hasArguments => JS('bool', '"args" in #', _typeData); |
| 1819 List get _arguments => JS('JSExtendableArray', '#.args', _typeData); | 1851 List get _arguments => JS('JSExtendableArray', '#.args', _typeData); |
| 1820 | 1852 |
| 1821 bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData); | 1853 bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData); |
| 1822 List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData); | 1854 List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData); |
| 1823 | 1855 |
| 1824 bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData); | 1856 bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData); |
| 1825 get _namedArguments => JS('=Object', '#.named', _typeData); | 1857 get _namedArguments => JS('=Object', '#.named', _typeData); |
| 1858 bool get isOriginalDeclaration => true; |
| 1826 | 1859 |
| 1827 TypeMirror get returnType { | 1860 TypeMirror get returnType { |
| 1828 if (_cachedReturnType != null) return _cachedReturnType; | 1861 if (_cachedReturnType != null) return _cachedReturnType; |
| 1829 if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType; | 1862 if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType; |
| 1830 if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType; | 1863 if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType; |
| 1831 return _cachedReturnType = | 1864 return _cachedReturnType = |
| 1832 typeMirrorFromRuntimeTypeRepresentation(_returnType); | 1865 typeMirrorFromRuntimeTypeRepresentation(this, _returnType); |
| 1833 } | 1866 } |
| 1834 | 1867 |
| 1835 List<ParameterMirror> get parameters { | 1868 List<ParameterMirror> get parameters { |
| 1836 if (_cachedParameters != null) return _cachedParameters; | 1869 if (_cachedParameters != null) return _cachedParameters; |
| 1837 List result = []; | 1870 List result = []; |
| 1838 int parameterCount = 0; | 1871 int parameterCount = 0; |
| 1839 if (_hasArguments) { | 1872 if (_hasArguments) { |
| 1840 for (var type in _arguments) { | 1873 for (var type in _arguments) { |
| 1841 result.add( | 1874 result.add( |
| 1842 new JsParameterMirror('argument${parameterCount++}', this, type)); | 1875 new JsParameterMirror('argument${parameterCount++}', this, type)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 s += 'void'; | 1928 s += 'void'; |
| 1896 } else if (_hasReturnType) { | 1929 } else if (_hasReturnType) { |
| 1897 s += runtimeTypeToString(_returnType); | 1930 s += runtimeTypeToString(_returnType); |
| 1898 } else { | 1931 } else { |
| 1899 s += 'dynamic'; | 1932 s += 'dynamic'; |
| 1900 } | 1933 } |
| 1901 return _cachedToString = "$s'"; | 1934 return _cachedToString = "$s'"; |
| 1902 } | 1935 } |
| 1903 } | 1936 } |
| 1904 | 1937 |
| 1905 TypeMirror typeMirrorFromRuntimeTypeRepresentation(type) { | 1938 int findTypeVariableIndex(List<TypeVariableMirror> typeVariables, String name) { |
| 1906 if (type == null) return JsMirrorSystem._dynamicType; | 1939 for (int i = 0; i < typeVariables.length; i++) { |
| 1907 String representation = runtimeTypeToString(type); | 1940 if (typeVariables[i].simpleName == s(name)) { |
| 1908 if (representation == null) return reflectClass(Function); | 1941 return i; |
| 1909 return reflectType(createRuntimeType(representation)); | 1942 } |
| 1943 } |
| 1944 throw new ArgumentError('Type variable not present in list.'); |
| 1910 } | 1945 } |
| 1911 | 1946 |
| 1912 TypeMirror computeTypeMirror(DeclarationMirror owner, var type) { | 1947 getMetadata(int index) => JS('', 'init.metadata[#]', index); |
| 1913 if (type is! int) { | 1948 |
| 1914 return typeMirrorFromRuntimeTypeRepresentation(type); | 1949 TypeMirror typeMirrorFromRuntimeTypeRepresentation( |
| 1915 } | 1950 DeclarationMirror owner, |
| 1916 | 1951 var /*int|List|JsFunction*/ type) { |
| 1917 ClassMirror ownerClass; | 1952 ClassMirror ownerClass; |
| 1918 DeclarationMirror context = owner; | 1953 DeclarationMirror context = owner; |
| 1919 while(context != null) { | 1954 while(context != null) { |
| 1920 if (context is ClassMirror) { | 1955 if (context is ClassMirror) { |
| 1921 ownerClass = context; | 1956 ownerClass = context; |
| 1922 break; | 1957 break; |
| 1923 } | 1958 } |
| 1924 context = context.owner; | 1959 context = context.owner; |
| 1925 } | 1960 } |
| 1926 | 1961 |
| 1927 TypeVariable typeVariable = JS('', 'init.metadata[#]', type); | 1962 String representation; |
| 1928 Symbol name = new Symbol(typeVariable.name); | 1963 if (type == null){ |
| 1929 List<TypeVariableMirror> typeVariables = ownerClass.typeVariables; | 1964 return JsMirrorSystem._dynamicType; |
| 1930 for (int i = 0; i < typeVariables.length; i++) { | 1965 } else if (ownerClass == null) { |
| 1931 if (typeVariables[i].simpleName == name) { | 1966 representation = runtimeTypeToString(type); |
| 1932 if (ownerClass.isOriginalDeclaration) { | 1967 } else if (ownerClass.isOriginalDeclaration) { |
| 1933 return typeVariables[i]; | 1968 if (type is int) { |
| 1934 } else { | 1969 // [type] represents a type variable so in the context of an original |
| 1935 return ownerClass.typeArguments[i]; | 1970 // declaration the corresponding type variable should be returned. |
| 1936 } | 1971 TypeVariable typeVariable = getMetadata(type); |
| 1972 List<TypeVariableMirror> typeVariables = ownerClass.typeVariables; |
| 1973 int index = findTypeVariableIndex(typeVariables, typeVariable.name); |
| 1974 return typeVariables[index]; |
| 1975 } else { |
| 1976 // Nested type variables will be retrieved lazily (the integer |
| 1977 // representation is kept in the string) so they are not processed here. |
| 1978 representation = runtimeTypeToString(type); |
| 1937 } | 1979 } |
| 1980 } else { |
| 1981 String substituteTypeVariable(int index) { |
| 1982 TypeVariable typeVariable = getMetadata(index); |
| 1983 int variableIndex = |
| 1984 findTypeVariableIndex(ownerClass.typeVariables, typeVariable.name); |
| 1985 var typeArgument = ownerClass.typeArguments[variableIndex]; |
| 1986 assert(typeArgument is JsClassMirror || |
| 1987 typeArgument is JsTypeBoundClassMirror); |
| 1988 return typeArgument._mangledName; |
| 1989 } |
| 1990 representation = |
| 1991 runtimeTypeToString(type, onTypeVariable: substituteTypeVariable); |
| 1938 } | 1992 } |
| 1993 if (representation != null) { |
| 1994 return reflectType(createRuntimeType(representation)); |
| 1995 } |
| 1996 return reflectClass(Function); |
| 1939 } | 1997 } |
| 1940 | 1998 |
| 1941 Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) { | 1999 Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) { |
| 1942 if (owner == null) return simpleName; | 2000 if (owner == null) return simpleName; |
| 1943 String ownerName = n(owner.qualifiedName); | 2001 String ownerName = n(owner.qualifiedName); |
| 1944 return s('$ownerName.${n(simpleName)}'); | 2002 return s('$ownerName.${n(simpleName)}'); |
| 1945 } | 2003 } |
| 1946 | 2004 |
| 1947 List extractMetadata(victim) { | 2005 List extractMetadata(victim) { |
| 1948 preserveMetadata(); | 2006 preserveMetadata(); |
| 1949 var metadataFunction = JS('', '#["@"]', victim); | 2007 var metadataFunction = JS('', '#["@"]', victim); |
| 1950 if (metadataFunction != null) return JS('', '#()', metadataFunction); | 2008 if (metadataFunction != null) return JS('', '#()', metadataFunction); |
| 1951 if (JS('String', 'typeof #', victim) != 'function') return const []; | 2009 if (JS('String', 'typeof #', victim) != 'function') return const []; |
| 1952 String source = JS('String', 'Function.prototype.toString.call(#)', victim); | 2010 String source = JS('String', 'Function.prototype.toString.call(#)', victim); |
| 1953 int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}')); | 2011 int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}')); |
| 1954 if (index == -1) return const []; | 2012 if (index == -1) return const []; |
| 1955 index++; | 2013 index++; |
| 1956 int endQuote = source.indexOf('"', index); | 2014 int endQuote = source.indexOf('"', index); |
| 1957 return source.substring(index, endQuote).split(',').map(int.parse).map( | 2015 return source.substring(index, endQuote).split(',').map(int.parse).map( |
| 1958 (int i) => JS('', 'init.metadata[#]', i)).toList(); | 2016 (int i) => getMetadata(i)).toList(); |
| 1959 } | 2017 } |
| 1960 | 2018 |
| 1961 List<JsVariableMirror> parseCompactFieldSpecification( | 2019 List<JsVariableMirror> parseCompactFieldSpecification( |
| 1962 JsDeclarationMirror owner, | 2020 JsDeclarationMirror owner, |
| 1963 fieldSpecification, | 2021 fieldSpecification, |
| 1964 bool isStatic, | 2022 bool isStatic, |
| 1965 List<Mirror> result) { | 2023 List<Mirror> result) { |
| 1966 List fieldsMetadata = null; | 2024 List fieldsMetadata = null; |
| 1967 List<String> fieldNames; | 2025 List<String> fieldNames; |
| 1968 if (fieldSpecification is List) { | 2026 if (fieldSpecification is List) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2070 | 2128 |
| 2071 // TODO(ahe): Remove this class and call noSuchMethod instead. | 2129 // TODO(ahe): Remove this class and call noSuchMethod instead. |
| 2072 class UnimplementedNoSuchMethodError extends Error | 2130 class UnimplementedNoSuchMethodError extends Error |
| 2073 implements NoSuchMethodError { | 2131 implements NoSuchMethodError { |
| 2074 final String _message; | 2132 final String _message; |
| 2075 | 2133 |
| 2076 UnimplementedNoSuchMethodError(this._message); | 2134 UnimplementedNoSuchMethodError(this._message); |
| 2077 | 2135 |
| 2078 String toString() => "Unsupported operation: $_message"; | 2136 String toString() => "Unsupported operation: $_message"; |
| 2079 } | 2137 } |
| OLD | NEW |