| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // Patch library for dart:mirrors. |
| |
| import 'dart:_js_helper' show patch; |
| import 'dart:_js_mirrors' as js; |
| import 'dart:_runtime' as dart; |
| |
| @patch |
| class MirrorSystem { |
| @patch |
| LibraryMirror findLibrary(Symbol libraryName) { |
| return libraries.values |
| .singleWhere((library) => library.simpleName == libraryName); |
| } |
| |
| @patch |
| static String getName(Symbol symbol) => js.getName(symbol); |
| |
| @patch |
| static Symbol getSymbol(String name, [LibraryMirror library]) { |
| return js.getSymbol(name, library); |
| } |
| } |
| |
| @patch |
| MirrorSystem currentMirrorSystem() => js.currentJsMirrorSystem; |
| |
| @patch |
| InstanceMirror reflect(Object reflectee) => js.reflect(reflectee); |
| |
| @patch |
| ClassMirror reflectClass(Type key) { |
| if (key is! Type || key == dynamic) { |
| throw ArgumentError('$key does not denote a class'); |
| } |
| TypeMirror tm = reflectType(key); |
| if (tm is! ClassMirror) { |
| throw ArgumentError("$key does not denote a class"); |
| } |
| return (tm as ClassMirror).originalDeclaration; |
| } |
| |
| @patch |
| TypeMirror reflectType(Type type, [List<Type> typeArguments]) { |
| if (typeArguments != null) { |
| type = _instantiateClass(type, typeArguments); |
| } |
| return js.reflectType(type); |
| } |
| |
| /// Instantiates the generic class [type] with [typeArguments] and returns the |
| /// result. |
| /// |
| /// [type] may be instantiated with type arguments already. In that case, they |
| /// are ignored. For example calling this function with `(List<int>, [String])` |
| /// and `(List<dynamic>, [String])` will produce `List<String>` in both cases. |
| Type _instantiateClass(Type type, List<Type> typeArguments) { |
| var unwrapped = dart.unwrapType(type); |
| var genericClass = dart.getGenericClass(unwrapped); |
| if (genericClass == null) { |
| throw ArgumentError('Type `$type` must be generic to apply ' |
| 'type arguments: `$typeArguments`.'); |
| } |
| |
| var typeArgsLenth = typeArguments.length; |
| var unwrappedArgs = List(typeArgsLenth); |
| for (int i = 0; i < typeArgsLenth; i++) { |
| unwrappedArgs[i] = dart.unwrapType(typeArguments[i]); |
| } |
| var typeFormals = dart.getGenericTypeFormals(genericClass); |
| if (typeFormals.length != typeArgsLenth) { |
| throw ArgumentError('Type `$type` has ${typeFormals.length} type ' |
| 'parameters, but $typeArgsLenth type arguments were ' |
| 'passed: `$typeArguments`.'); |
| } |
| // TODO(jmesserly): this does not validate bounds, as we don't have them |
| // available at runtime. Consider storing them when dart:mirrors is enabled. |
| return dart.wrapType(dart.instantiateClass(genericClass, unwrappedArgs)); |
| } |