| // 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)); | |
| } |