Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(643)

Unified Diff: sdk/lib/_internal/compiler/js_lib/js_mirrors.dart

Issue 1212513002: sdk files reorganization to make dart2js a proper package (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: renamed Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
diff --git a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
deleted file mode 100644
index 5815a32be154d016d57f2d1acd4166c2c930b57a..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
+++ /dev/null
@@ -1,3055 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library dart._js_mirrors;
-
-import 'dart:_js_embedded_names' show
- JsGetName,
- ALL_CLASSES,
- LAZIES,
- LIBRARIES,
- STATICS,
- TYPE_INFORMATION,
- TYPEDEF_PREDICATE_PROPERTY_NAME,
- TYPEDEF_TYPE_PROPERTY_NAME;
-
-import 'dart:collection' show
- UnmodifiableListView,
- UnmodifiableMapView;
-
-import 'dart:mirrors';
-
-import 'dart:_foreign_helper' show
- JS,
- JS_GET_FLAG,
- JS_CURRENT_ISOLATE,
- JS_CURRENT_ISOLATE_CONTEXT,
- JS_EMBEDDED_GLOBAL,
- JS_GET_NAME,
- JS_TYPEDEF_TAG,
- JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
- JS_FUNCTION_TYPE_VOID_RETURN_TAG,
- JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
- JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
- JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG;
-
-
-import 'dart:_internal' as _symbol_dev;
-
-import 'dart:_js_helper' show
- BoundClosure,
- CachedInvocation,
- Closure,
- JSInvocationMirror,
- JsCache,
- Null,
- Primitives,
- ReflectionInfo,
- RuntimeError,
- TearOffClosure,
- TypeVariable,
- UnimplementedNoSuchMethodError,
- createRuntimeType,
- createUnmangledInvocationMirror,
- getMangledTypeName,
- getMetadata,
- getType,
- getRuntimeType,
- isDartFunctionType,
- runtimeTypeToString,
- setRuntimeTypeInfo,
- throwInvalidReflectionError,
- TypeImpl,
- deferredLoadHook;
-
-import 'dart:_interceptors' show
- Interceptor,
- JSArray,
- JSExtendableArray,
- getInterceptor;
-
-import 'dart:_js_names';
-
-const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments';
-
-bool hasReflectableProperty(var jsFunction) {
- return JS('bool', '# in #', JS_GET_NAME(JsGetName.REFLECTABLE), jsFunction);
-}
-
-/// No-op method that is called to inform the compiler that tree-shaking needs
-/// to be disabled.
-disableTreeShaking() => preserveNames();
-
-/// No-op method that is called to inform the compiler that metadata must be
-/// preserved at runtime.
-preserveMetadata() {}
-
-/// No-op method that is called to inform the compiler that the compiler must
-/// preserve the URIs.
-preserveUris() {}
-
-/// No-op method that is called to inform the compiler that the compiler must
-/// preserve the library names.
-preserveLibraryNames() {}
-
-String getName(Symbol symbol) {
- preserveNames();
- return n(symbol);
-}
-
-class JsMirrorSystem implements MirrorSystem {
- UnmodifiableMapView<Uri, LibraryMirror> _cachedLibraries;
-
- final IsolateMirror isolate = new JsIsolateMirror();
-
- JsTypeMirror get dynamicType => _dynamicType;
- JsTypeMirror get voidType => _voidType;
-
- static final JsTypeMirror _dynamicType =
- new JsTypeMirror(const Symbol('dynamic'));
- static final JsTypeMirror _voidType = new JsTypeMirror(const Symbol('void'));
-
- static Map<String, List<LibraryMirror>> _librariesByName;
-
- // Will be set to `true` when we have installed a hook on [deferredLoadHook]
- // to avoid installing it multiple times.
- static bool _hasInstalledDeferredLoadHook = false;
-
- static Map<String, List<LibraryMirror>> get librariesByName {
- if (_librariesByName == null) {
- _librariesByName = computeLibrariesByName();
- if (!_hasInstalledDeferredLoadHook) {
- _hasInstalledDeferredLoadHook = true;
- // After a deferred import has been loaded new libraries might have
- // been created, so in the hook we erase _librariesByName, so it will be
- // recomputed on the next access.
- deferredLoadHook = () => _librariesByName = null;
- }
- }
- return _librariesByName;
- }
-
- Map<Uri, LibraryMirror> get libraries {
- if (_cachedLibraries != null) return _cachedLibraries;
- Map<Uri, LibraryMirror> result = new Map();
- for (List<LibraryMirror> list in librariesByName.values) {
- for (LibraryMirror library in list) {
- result[library.uri] = library;
- }
- }
- return _cachedLibraries =
- new UnmodifiableMapView<Uri, LibraryMirror>(result);
- }
-
- LibraryMirror findLibrary(Symbol libraryName) {
- return librariesByName[n(libraryName)].single;
- }
-
- static Map<String, List<LibraryMirror>> computeLibrariesByName() {
- disableTreeShaking();
- var result = new Map<String, List<LibraryMirror>>();
- var jsLibraries = JS_EMBEDDED_GLOBAL('JSExtendableArray|Null', LIBRARIES);
- if (jsLibraries == null) return result;
- for (List data in jsLibraries) {
- String name = data[0];
- String uriString = data[1];
- Uri uri;
- // The Uri has been compiled out. Create a URI from the simple name.
- if (uriString != "") {
- uri = Uri.parse(uriString);
- } else {
- uri = new Uri(scheme: 'https',
- host: 'dartlang.org',
- path: 'dart2js-stripped-uri',
- queryParameters: { 'lib': name });
- }
- List<String> classes = data[2];
- List<String> functions = data[3];
- var metadataFunction = data[4];
- var fields = data[5];
- bool isRoot = data[6];
- var globalObject = data[7];
- List metadata = (metadataFunction == null)
- ? const [] : JS('List', '#()', metadataFunction);
- var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
- libraries.add(
- new JsLibraryMirror(
- s(name), uri, classes, functions, metadata, fields, isRoot,
- globalObject));
- }
- return result;
- }
-}
-
-abstract class JsMirror implements Mirror {
- const JsMirror();
-
- String get _prettyName;
-
- String toString() => _prettyName;
-
- // 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();
- }
-}
-
-// This class is somewhat silly in the current implementation.
-class JsIsolateMirror extends JsMirror implements IsolateMirror {
- final _isolateContext = JS_CURRENT_ISOLATE_CONTEXT();
-
- String get _prettyName => 'Isolate';
-
- String get debugName {
- String id = _isolateContext == null ? 'X' : _isolateContext.id.toString();
- // Using name similar to what the VM uses.
- return '${n(rootLibrary.simpleName)}-$id';
- }
-
- bool get isCurrent => JS_CURRENT_ISOLATE_CONTEXT() == _isolateContext;
-
- LibraryMirror get rootLibrary {
- return currentJsMirrorSystem.libraries.values.firstWhere(
- (JsLibraryMirror library) => library._isRoot);
- }
-}
-
-abstract class JsDeclarationMirror extends JsMirror
- implements DeclarationMirror {
- final Symbol simpleName;
-
- const JsDeclarationMirror(this.simpleName);
-
- Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
-
- bool get isPrivate => n(simpleName).startsWith('_');
-
- bool get isTopLevel => owner != null && owner is LibraryMirror;
-
- // TODO(ahe): This should use qualifiedName.
- String toString() => "$_prettyName on '${n(simpleName)}'";
-
- List<JsMethodMirror> get _methods {
- throw new RuntimeError('Should not call _methods');
- }
-
- _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
- throw new RuntimeError('Should not call _invoke');
- }
-
- // TODO(ahe): Implement this.
- SourceLocation get location => throw new UnimplementedError();
-}
-
-class JsTypeVariableMirror extends JsTypeMirror implements TypeVariableMirror {
- final DeclarationMirror owner;
- final TypeVariable _typeVariable;
- final int _metadataIndex;
- TypeMirror _cachedUpperBound;
-
- JsTypeVariableMirror(TypeVariable typeVariable, this.owner,
- this._metadataIndex)
- : this._typeVariable = typeVariable,
- super(s(typeVariable.name));
-
- bool operator ==(other) {
- return (other is JsTypeVariableMirror &&
- simpleName == other.simpleName &&
- owner == other.owner);
- }
-
- int get hashCode {
- int code = 0x3FFFFFFF & (JsTypeVariableMirror).hashCode;
- code ^= 17 * simpleName.hashCode;
- code ^= 19 * owner.hashCode;
- return code;
- }
-
- String get _prettyName => 'TypeVariableMirror';
-
- bool get isTopLevel => false;
- bool get isStatic => false;
-
- TypeMirror get upperBound {
- if (_cachedUpperBound != null) return _cachedUpperBound;
- return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation(
- owner, getType(_typeVariable.bound));
- }
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-
- _asRuntimeType() => _metadataIndex;
-}
-
-class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
- JsTypeMirror(Symbol simpleName)
- : super(simpleName);
-
- String get _prettyName => 'TypeMirror';
-
- DeclarationMirror get owner => null;
-
- // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569.
- bool get isTopLevel => true;
-
- // TODO(ahe): Implement these.
- List<InstanceMirror> get metadata => throw new UnimplementedError();
-
- bool get hasReflectedType => false;
- Type get reflectedType {
- throw new UnsupportedError("This type does not support reflectedType");
- }
-
- List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
- List<TypeMirror> get typeArguments => const <TypeMirror>[];
-
- bool get isOriginalDeclaration => true;
- TypeMirror get originalDeclaration => this;
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-
- _asRuntimeType() {
- if (this == JsMirrorSystem._dynamicType) return null;
- if (this == JsMirrorSystem._voidType) return null;
- throw new RuntimeError('Should not call _asRuntimeType');
- }
-}
-
-class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
- implements LibraryMirror {
- final Uri _uri;
- final List<String> _classes;
- final List<String> _functions;
- final List _metadata;
- final String _compactFieldSpecification;
- final bool _isRoot;
- final _globalObject;
- List<JsMethodMirror> _cachedFunctionMirrors;
- List<VariableMirror> _cachedFields;
- UnmodifiableMapView<Symbol, ClassMirror> _cachedClasses;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedFunctions;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
- UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
- UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
- UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
- UnmodifiableListView<InstanceMirror> _cachedMetadata;
-
- JsLibraryMirror(Symbol simpleName,
- this._uri,
- this._classes,
- this._functions,
- this._metadata,
- this._compactFieldSpecification,
- this._isRoot,
- this._globalObject)
- : super(simpleName) {
- preserveLibraryNames();
- }
-
- String get _prettyName => 'LibraryMirror';
-
- Uri get uri {
- preserveUris();
- return _uri;
- }
-
- Symbol get qualifiedName => simpleName;
-
- List<JsMethodMirror> get _methods => _functionMirrors;
-
- Map<Symbol, ClassMirror> get __classes {
- if (_cachedClasses != null) return _cachedClasses;
- var result = new Map();
- for (String className in _classes) {
- var cls = reflectClassByMangledName(className);
- if (cls is ClassMirror) {
- cls = cls.originalDeclaration;
- }
- if (cls is JsClassMirror) {
- result[cls.simpleName] = cls;
- cls._owner = this;
- } else if (cls is JsTypedefMirror) {
- result[cls.simpleName] = cls;
- }
- }
- return _cachedClasses =
- new UnmodifiableMapView<Symbol, ClassMirror>(result);
- }
-
- InstanceMirror setField(Symbol fieldName, Object 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) {
- throw new NoSuchStaticMethodError.method(
- null, setterSymbol(fieldName), [arg], null);
- }
- mirror._setField(this, arg);
- return reflect(arg);
- }
-
- InstanceMirror getField(Symbol fieldName) {
- JsMirror mirror = __members[fieldName];
- if (mirror == null) {
- throw new NoSuchStaticMethodError.method(null, fieldName, [], null);
- }
- if (mirror is! MethodMirror) return reflect(mirror._getField(this));
- JsMethodMirror methodMirror = mirror;
- if (methodMirror.isGetter) return reflect(mirror._getField(this));
- assert(methodMirror.isRegularMethod);
- var getter = JS("", "#['\$getter']", methodMirror._jsFunction);
- if (getter == null) throw new UnimplementedError();
- return reflect(JS("", "#()", getter));
- }
-
- InstanceMirror invoke(Symbol memberName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
- if (namedArguments != null && !namedArguments.isEmpty) {
- throw new UnsupportedError('Named arguments are not implemented.');
- }
- JsDeclarationMirror mirror = __members[memberName];
-
- if (mirror is JsMethodMirror && !mirror.canInvokeReflectively()) {
- throwInvalidReflectionError(n(memberName));
- }
- if (mirror == null || mirror is JsMethodMirror && mirror.isSetter) {
- throw new NoSuchStaticMethodError.method(
- null, memberName, positionalArguments, namedArguments);
- }
- if (mirror is JsMethodMirror && !mirror.isGetter) {
- return reflect(mirror._invoke(positionalArguments, namedArguments));
- }
- return getField(memberName)
- .invoke(#call, positionalArguments, namedArguments);
- }
-
- _loadField(String name) {
- // TODO(ahe): What about lazily initialized fields? See
- // [JsClassMirror.getField].
-
- // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so we
- // shouldn't use [_globalObject] here.
- assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
- return JS('', '#[#]', JS_CURRENT_ISOLATE(), name);
- }
-
- void _storeField(String name, Object arg) {
- // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so we
- // shouldn't use [_globalObject] here.
- assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
- JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), name, arg);
- }
-
- List<JsMethodMirror> get _functionMirrors {
- if (_cachedFunctionMirrors != null) return _cachedFunctionMirrors;
- var result = new List<JsMethodMirror>();
- for (int i = 0; i < _functions.length; i++) {
- String name = _functions[i];
- var jsFunction = JS('', '#[#]', _globalObject, name);
- String unmangledName = mangledGlobalNames[name];
- if (unmangledName == null ||
- JS('bool', "!!#['\$getterStub']", jsFunction)) {
- // If there is no unmangledName, [jsFunction] is either a synthetic
- // implementation detail, or something that is excluded
- // by @MirrorsUsed.
- // If it has a getterStub property it is a synthetic stub.
- // TODO(floitsch): Remove the getterStub hack.
- continue;
- }
- bool isConstructor = unmangledName.startsWith('new ');
- bool isStatic = !isConstructor; // Top-level functions are static, but
- // constructors are not.
- if (isConstructor) {
- unmangledName = unmangledName.substring(4).replaceAll(r'$', '.');
- }
- JsMethodMirror mirror =
- new JsMethodMirror.fromUnmangledName(
- unmangledName, jsFunction, isStatic, isConstructor);
- result.add(mirror);
- mirror._owner = this;
- }
- return _cachedFunctionMirrors = result;
- }
-
- List<VariableMirror> get _fields {
- if (_cachedFields != null) return _cachedFields;
- var result = <VariableMirror>[];
- parseCompactFieldSpecification(
- this, _compactFieldSpecification, true, result);
- return _cachedFields = result;
- }
-
- Map<Symbol, MethodMirror> get __functions {
- if (_cachedFunctions != null) return _cachedFunctions;
- var result = new Map();
- for (JsMethodMirror mirror in _functionMirrors) {
- if (!mirror.isConstructor) result[mirror.simpleName] = mirror;
- }
- return _cachedFunctions =
- new UnmodifiableMapView<Symbol, MethodMirror>(result);
- }
-
- Map<Symbol, MethodMirror> get __getters {
- if (_cachedGetters != null) return _cachedGetters;
- var result = new Map();
- // TODO(ahe): Implement this.
- return _cachedGetters =
- new UnmodifiableMapView<Symbol, MethodMirror>(result);
- }
-
- Map<Symbol, MethodMirror> get __setters {
- if (_cachedSetters != null) return _cachedSetters;
- var result = new Map();
- // TODO(ahe): Implement this.
- return _cachedSetters =
- new UnmodifiableMapView<Symbol, MethodMirror>(result);
- }
-
- Map<Symbol, VariableMirror> get __variables {
- if (_cachedVariables != null) return _cachedVariables;
- var result = new Map();
- for (JsVariableMirror mirror in _fields) {
- result[mirror.simpleName] = mirror;
- }
- return _cachedVariables =
- new UnmodifiableMapView<Symbol, VariableMirror>(result);
- }
-
- Map<Symbol, Mirror> get __members {
- if (_cachedMembers != null) return _cachedMembers;
- Map<Symbol, Mirror> result = new Map.from(__classes);
- addToResult(Symbol key, Mirror value) {
- result[key] = value;
- }
- __functions.forEach(addToResult);
- __getters.forEach(addToResult);
- __setters.forEach(addToResult);
- __variables.forEach(addToResult);
- return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
- }
-
- Map<Symbol, DeclarationMirror> get declarations {
- if (_cachedDeclarations != null) return _cachedDeclarations;
- var result = new Map<Symbol, DeclarationMirror>();
- addToResult(Symbol key, Mirror value) {
- result[key] = value;
- }
- __members.forEach(addToResult);
- return _cachedDeclarations =
- new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
- }
-
- List<InstanceMirror> get metadata {
- if (_cachedMetadata != null) return _cachedMetadata;
- preserveMetadata();
- return _cachedMetadata =
- new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
- }
-
- // TODO(ahe): Test this getter.
- DeclarationMirror get owner => null;
-
- List<LibraryDependencyMirror> get libraryDependencies
- => throw new UnimplementedError();
-}
-
-String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
-
-Symbol s(String name) {
- if (name == null) return null;
- return new _symbol_dev.Symbol.unvalidated(name);
-}
-
-Symbol setterSymbol(Symbol symbol) => s("${n(symbol)}=");
-
-final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem();
-
-InstanceMirror reflect(Object reflectee) {
- if (reflectee is Closure) {
- return new JsClosureMirror(reflectee);
- } else {
- return new JsInstanceMirror(reflectee);
- }
-}
-
-TypeMirror reflectType(Type key) {
- return reflectClassByMangledName(getMangledTypeName(key));
-}
-
-TypeMirror reflectClassByMangledName(String mangledName) {
- String unmangledName = mangledGlobalNames[mangledName];
- if (mangledName == 'dynamic') return JsMirrorSystem._dynamicType;
- if (mangledName == 'void') return JsMirrorSystem._voidType;
- if (unmangledName == null) unmangledName = mangledName;
- return reflectClassByName(s(unmangledName), mangledName);
-}
-
-var classMirrors;
-
-TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
- if (classMirrors == null) classMirrors = JsCache.allocate();
- var mirror = JsCache.fetch(classMirrors, mangledName);
- if (mirror != null) return mirror;
- disableTreeShaking();
- int typeArgIndex = mangledName.indexOf("<");
- if (typeArgIndex != -1) {
- TypeMirror originalDeclaration =
- reflectClassByMangledName(mangledName.substring(0, typeArgIndex))
- .originalDeclaration;
- if (originalDeclaration is JsTypedefMirror) {
- throw new UnimplementedError();
- }
- mirror = new JsTypeBoundClassMirror(originalDeclaration,
- // Remove the angle brackets enclosing the type arguments.
- mangledName.substring(typeArgIndex + 1, mangledName.length - 1));
- JsCache.update(classMirrors, mangledName, mirror);
- return mirror;
- }
- var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES);
- var constructor = JS('var', '#[#]', allClasses, mangledName);
- if (constructor == null) {
- // Probably an intercepted class.
- // TODO(ahe): How to handle intercepted classes?
- throw new UnsupportedError('Cannot find class for: ${n(symbol)}');
- }
- var descriptor = JS('', '#["@"]', constructor);
- var fields;
- var fieldsMetadata;
- if (descriptor == null) {
- // This is a native class, or an intercepted class.
- // TODO(ahe): Preserve descriptor for such classes.
- } else if (JS('bool', '# in #',
- TYPEDEF_PREDICATE_PROPERTY_NAME, descriptor)) {
- // Typedefs are represented as normal classes with two special properties:
- // TYPEDEF_PREDICATE_PROPERTY_NAME and TYPEDEF_TYPE_PROPERTY_NAME.
- // For example:
- // MyTypedef: {
- // "^": "Object;",
- // $typedefType: 58,
- // $$isTypedef: true
- // }
- // The typedefType is the index into the metadata table.
- int index = JS('int', '#[#]', descriptor, TYPEDEF_TYPE_PROPERTY_NAME);
- mirror = new JsTypedefMirror(symbol, mangledName, getType(index));
- } else {
- fields = JS('', '#[#]', descriptor,
- JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY));
- if (fields is List) {
- fieldsMetadata = fields.getRange(1, fields.length).toList();
- fields = fields[0];
- }
- if (fields is! String) {
- // TODO(ahe): This is CSP mode. Find a way to determine the
- // fields of this class.
- fields = '';
- }
- }
-
- if (mirror == null) {
- var superclassName = fields.split(';')[0];
- var mixins = superclassName.split('+');
- if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
- mirror = reflectMixinApplication(mixins, mangledName);
- } else {
- ClassMirror classMirror = new JsClassMirror(
- symbol, mangledName, constructor, fields, fieldsMetadata);
- List typeVariables =
- JS('JSExtendableArray|Null', '#.prototype["<>"]', constructor);
- if (typeVariables == null || typeVariables.length == 0) {
- mirror = classMirror;
- } else {
- String typeArguments = 'dynamic';
- for (int i = 1; i < typeVariables.length; i++) {
- typeArguments += ',dynamic';
- }
- mirror = new JsTypeBoundClassMirror(classMirror, typeArguments);
- }
- }
- }
-
- JsCache.update(classMirrors, mangledName, mirror);
- return mirror;
-}
-
-Map<Symbol, MethodMirror> filterMethods(List<MethodMirror> methods) {
- var result = new Map();
- for (JsMethodMirror method in methods) {
- if (!method.isConstructor && !method.isGetter && !method.isSetter) {
- result[method.simpleName] = method;
- }
- }
- return result;
-}
-
-Map<Symbol, MethodMirror> filterConstructors(methods) {
- var result = new Map();
- for (JsMethodMirror method in methods) {
- if (method.isConstructor) {
- result[method.simpleName] = method;
- }
- }
- return result;
-}
-
-Map<Symbol, MethodMirror> filterGetters(List<MethodMirror> methods,
- Map<Symbol, VariableMirror> fields) {
- var result = new Map();
- for (JsMethodMirror method in methods) {
- if (method.isGetter) {
-
- // TODO(ahe): This is a hack to remove getters corresponding to a field.
- if (fields[method.simpleName] != null) continue;
-
- result[method.simpleName] = method;
- }
- }
- return result;
-}
-
-Map<Symbol, MethodMirror> filterSetters(List<MethodMirror> methods,
- Map<Symbol, VariableMirror> fields) {
- var result = new Map();
- for (JsMethodMirror method in methods) {
- if (method.isSetter) {
-
- // TODO(ahe): This is a hack to remove setters corresponding to a field.
- String name = n(method.simpleName);
- name = name.substring(0, name.length - 1); // Remove '='.
- if (fields[s(name)] != null) continue;
-
- result[method.simpleName] = method;
- }
- }
- return result;
-}
-
-Map<Symbol, Mirror> filterMembers(List<MethodMirror> methods,
- Map<Symbol, VariableMirror> variables) {
- Map<Symbol, Mirror> result = new Map.from(variables);
- for (JsMethodMirror method in methods) {
- if (method.isSetter) {
- String name = n(method.simpleName);
- name = name.substring(0, name.length - 1);
- // Filter-out setters corresponding to variables.
- if (result[s(name)] is VariableMirror) continue;
- }
- // Constructors aren't 'members'.
- if (method.isConstructor) continue;
- // Filter out synthetic tear-off stubs
- if (JS('bool', r'!!#.$getterStub', method._jsFunction)) continue;
- // Use putIfAbsent to filter-out getters corresponding to variables.
- result.putIfAbsent(method.simpleName, () => method);
- }
- return result;
-}
-
-int counter = 0;
-
-ClassMirror reflectMixinApplication(mixinNames, String mangledName) {
- disableTreeShaking();
- var mixins = [];
- for (String mangledName in mixinNames) {
- mixins.add(reflectClassByMangledName(mangledName));
- }
- var it = mixins.iterator;
- it.moveNext();
- var superclass = it.current;
- while (it.moveNext()) {
- superclass = new JsMixinApplication(superclass, it.current, mangledName);
- }
- return superclass;
-}
-
-class JsMixinApplication extends JsTypeMirror with JsObjectMirror
- implements ClassMirror {
- final ClassMirror superclass;
- final ClassMirror mixin;
- Symbol _cachedSimpleName;
- Map<Symbol, MethodMirror> _cachedInstanceMembers;
-
- JsMixinApplication(ClassMirror superclass, ClassMirror mixin,
- String mangledName)
- : this.superclass = superclass,
- this.mixin = mixin,
- super(s(mangledName));
-
- String get _prettyName => 'ClassMirror';
-
- Symbol get simpleName {
- if (_cachedSimpleName != null) return _cachedSimpleName;
- String superName = n(superclass.qualifiedName);
- return _cachedSimpleName = (superName.contains(' with '))
- ? s('$superName, ${n(mixin.qualifiedName)}')
- : s('$superName with ${n(mixin.qualifiedName)}');
- }
-
- Symbol get qualifiedName => simpleName;
-
- // TODO(ahe): Remove this method, only here to silence warning.
- get _mixin => mixin;
-
- Map<Symbol, Mirror> get __members => _mixin.__members;
-
- Map<Symbol, MethodMirror> get __methods => _mixin.__methods;
-
- Map<Symbol, MethodMirror> get __getters => _mixin.__getters;
-
- Map<Symbol, MethodMirror> get __setters => _mixin.__setters;
-
- Map<Symbol, VariableMirror> get __variables => _mixin.__variables;
-
- Map<Symbol, DeclarationMirror> get declarations => mixin.declarations;
-
- Map<Symbol, MethodMirror> get instanceMembers {
- if (_cachedInstanceMembers == null) {
- var result = new Map<Symbol, MethodMirror>();
- if (superclass != null) {
- result.addAll(superclass.instanceMembers);
- }
- result.addAll(mixin.instanceMembers);
- _cachedInstanceMembers = result;
- }
- return _cachedInstanceMembers;
- }
-
- Map<Symbol, MethodMirror> get staticMembers => mixin.staticMembers;
-
- _asRuntimeType() => null;
-
- InstanceMirror invoke(
- Symbol memberName,
- List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) {
- throw new NoSuchStaticMethodError.method(
- null, memberName, positionalArguments, namedArguments);
- }
-
- InstanceMirror getField(Symbol fieldName) {
- throw new NoSuchStaticMethodError.method(null, fieldName, null, null);
- }
-
- InstanceMirror setField(Symbol fieldName, Object arg) {
- throw new NoSuchStaticMethodError.method(
- null, setterSymbol(fieldName), [arg], null);
- }
-
- List<ClassMirror> get superinterfaces => [mixin];
-
- Map<Symbol, MethodMirror> get __constructors => _mixin.__constructors;
-
- InstanceMirror newInstance(
- Symbol constructorName,
- List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) {
- throw new UnsupportedError(
- "Can't instantiate mixin application '${n(qualifiedName)}'");
- }
-
- bool get isOriginalDeclaration => true;
-
- ClassMirror get originalDeclaration => this;
-
- // TODO(ahe): Implement this.
- List<TypeVariableMirror> get typeVariables {
- throw new UnimplementedError();
- }
-
- List<TypeMirror> get typeArguments => const <TypeMirror>[];
-
- bool get isAbstract => throw new UnimplementedError();
-
- bool get isEnum => throw new UnimplementedError();
-
- bool isSubclassOf(ClassMirror other) {
- superclass.isSubclassOf(other) || mixin.isSubclassOf(other);
- }
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
-
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-}
-
-abstract class JsObjectMirror implements ObjectMirror {
-}
-
-class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
- final reflectee;
-
- JsInstanceMirror(this.reflectee);
-
- bool get hasReflectee => true;
-
- ClassMirror get type {
- // The spec guarantees that `null` is the singleton instance of the `Null`
- // class.
- if (reflectee == null) return reflectClass(Null);
- return reflectType(getRuntimeType(reflectee));
- }
-
- InstanceMirror invoke(Symbol memberName,
- List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) {
- if (namedArguments == null) namedArguments = const {};
- // We can safely pass positionalArguments to _invoke as it will wrap it in
- // a JSArray if needed.
- return _invoke(memberName, JSInvocationMirror.METHOD,
- positionalArguments, namedArguments);
- }
-
- InstanceMirror _invokeMethodWithNamedArguments(
- String reflectiveName,
- List positionalArguments, Map<Symbol,dynamic> namedArguments) {
- assert(namedArguments.isNotEmpty);
- var interceptor = getInterceptor(reflectee);
-
- var jsFunction = JS('', '#[#]', interceptor, reflectiveName);
- if (jsFunction == null) {
- // TODO(ahe): Invoke noSuchMethod.
- throw new UnimplementedNoSuchMethodError(
- 'Invoking noSuchMethod with named arguments not implemented');
- }
- ReflectionInfo info = new ReflectionInfo(jsFunction);
- if (jsFunction == null) {
- // TODO(ahe): Invoke noSuchMethod.
- throw new UnimplementedNoSuchMethodError(
- 'Invoking noSuchMethod with named arguments not implemented');
- }
-
- positionalArguments = new List.from(positionalArguments);
- // Check the number of positional arguments is valid.
- if (info.requiredParameterCount != positionalArguments.length) {
- // TODO(ahe): Invoke noSuchMethod.
- throw new UnimplementedNoSuchMethodError(
- 'Invoking noSuchMethod with named arguments not implemented');
- }
- var defaultArguments = new Map();
- for (int i = 0; i < info.optionalParameterCount; i++) {
- var parameterName = info.parameterName(i + info.requiredParameterCount);
- var defaultValue =
- getMetadata(info.defaultValue(i + info.requiredParameterCount));
- defaultArguments[parameterName] = defaultValue;
- }
- namedArguments.forEach((Symbol symbol, value) {
- String parameter = n(symbol);
- if (defaultArguments.containsKey(parameter)) {
- defaultArguments[parameter] = value;
- } else {
- // Extraneous named argument.
- // TODO(ahe): Invoke noSuchMethod.
- throw new UnimplementedNoSuchMethodError(
- 'Invoking noSuchMethod with named arguments not implemented');
- }
- });
- positionalArguments.addAll(defaultArguments.values);
- // TODO(ahe): Handle intercepted methods.
- return reflect(
- JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments));
- }
-
- /// Grabs hold of the class-specific invocation cache for the reflectee.
- /// All reflectees with the same class share the same cache. The cache
- /// maps reflective names to cached invocation objects with enough decoded
- /// reflective information to know how to to invoke a specific member.
- get _classInvocationCache {
- String cacheName = Primitives.mirrorInvokeCacheName;
- var cacheHolder = (reflectee == null) ? getInterceptor(null) : reflectee;
- var cache = JS('', r'#.constructor[#]', cacheHolder, cacheName);
- if (cache == null) {
- cache = JsCache.allocate();
- JS('void', r'#.constructor[#] = #', cacheHolder, cacheName, cache);
- }
- return cache;
- }
-
- String _computeReflectiveName(Symbol symbolName, int type,
- List positionalArguments,
- Map<Symbol, dynamic> namedArguments) {
- String name = n(symbolName);
- switch (type) {
- case JSInvocationMirror.GETTER: return name;
- case JSInvocationMirror.SETTER: return '$name=';
- case JSInvocationMirror.METHOD:
- if (namedArguments.isNotEmpty) return '$name*';
- int nbArgs = positionalArguments.length as int;
- return "$name:$nbArgs";
- }
- throw new RuntimeError("Could not compute reflective name for $name");
- }
-
- /**
- * Returns a `CachedInvocation` or `CachedNoSuchMethodInvocation` for the
- * given member.
- *
- * Caches the result.
- */
- _getCachedInvocation(Symbol name, int type, String reflectiveName,
- List positionalArguments, Map<Symbol,dynamic> namedArguments) {
-
- var cache = _classInvocationCache;
- var cacheEntry = JsCache.fetch(cache, reflectiveName);
- var result;
- if (cacheEntry == null) {
- disableTreeShaking();
- String mangledName = reflectiveNames[reflectiveName];
- List<String> argumentNames = const [];
-
- // TODO(ahe): We don't need to create an invocation mirror here. The
- // logic from JSInvocationMirror.getCachedInvocation could easily be
- // inlined here.
- Invocation invocation = createUnmangledInvocationMirror(
- name, mangledName, type, positionalArguments, argumentNames);
-
- cacheEntry =
- JSInvocationMirror.getCachedInvocation(invocation, reflectee);
- JsCache.update(cache, reflectiveName, cacheEntry);
- }
- return cacheEntry;
- }
-
- bool _isReflectable(CachedInvocation cachedInvocation) {
- // TODO(floitsch): tear-off closure does not guarantee that the
- // function is reflectable.
- var method = cachedInvocation.jsFunction;
- return hasReflectableProperty(method) || reflectee is TearOffClosure;
- }
-
- /// Invoke the member specified through name and type on the reflectee.
- /// As a side-effect, this populates the class-specific invocation cache
- /// for the reflectee.
- InstanceMirror _invoke(Symbol name,
- int type,
- List positionalArguments,
- Map<Symbol,dynamic> namedArguments) {
- String reflectiveName =
- _computeReflectiveName(name, type, positionalArguments, namedArguments);
-
- if (namedArguments.isNotEmpty) {
- // TODO(floitsch): first, make sure it's not a getter.
- return _invokeMethodWithNamedArguments(
- reflectiveName, positionalArguments, namedArguments);
- }
- var cacheEntry = _getCachedInvocation(
- name, type, reflectiveName, positionalArguments, namedArguments);
-
- if (cacheEntry.isNoSuchMethod || !_isReflectable(cacheEntry)) {
- // Could be that we want to invoke a getter, or get a method.
- if (type == JSInvocationMirror.METHOD && _instanceFieldExists(name)) {
- return getField(name).invoke(
- #call, positionalArguments, namedArguments);
- }
-
- if (type == JSInvocationMirror.SETTER) {
- // For setters we report the setter name "field=".
- name = s("${n(name)}=");
- }
-
- if (!cacheEntry.isNoSuchMethod) {
- // Not reflectable.
- throwInvalidReflectionError(reflectiveName);
- }
-
- String mangledName = reflectiveNames[reflectiveName];
- // TODO(ahe): Get the argument names.
- List<String> argumentNames = [];
- Invocation invocation = createUnmangledInvocationMirror(
- name, mangledName, type, positionalArguments, argumentNames);
- return reflect(cacheEntry.invokeOn(reflectee, invocation));
- } else {
- return reflect(cacheEntry.invokeOn(reflectee, positionalArguments));
- }
- }
-
- InstanceMirror setField(Symbol fieldName, Object arg) {
- _invoke(fieldName, JSInvocationMirror.SETTER, [arg], const {});
- return reflect(arg);
- }
-
- // JS helpers for getField optimizations.
- static bool isUndefined(x)
- => JS('bool', 'typeof # == "undefined"', x);
- static bool isMissingCache(x)
- => JS('bool', 'typeof # == "number"', x);
- static bool isMissingProbe(Symbol symbol)
- => JS('bool', 'typeof #.\$p == "undefined"', symbol);
- static bool isEvalAllowed()
- => !JS_GET_FLAG("USE_CONTENT_SECURITY_POLICY");
-
-
- /// The getter cache is lazily allocated after a couple
- /// of invocations of [InstanceMirror.getField]. The delay is
- /// used to avoid too aggressive caching and dynamic function
- /// generation for rarely used mirrors. The cache is specific to
- /// this [InstanceMirror] and maps reflective names to functions
- /// that will invoke the corresponding getter on the reflectee.
- /// The reflectee is passed to the function as the first argument
- /// to avoid the overhead of fetching it from this mirror repeatedly.
- /// The cache is lazily initialized to a JS object so we can
- /// benefit from "map transitions" in the underlying JavaScript
- /// engine to speed up cache probing.
- var _getterCache = 4;
-
- bool _instanceFieldExists(Symbol name) {
- int getterType = JSInvocationMirror.GETTER;
- String getterName =
- _computeReflectiveName(name, getterType, const [], const {});
- var getterCacheEntry = _getCachedInvocation(
- name, getterType, getterName, const [], const {});
- return !getterCacheEntry.isNoSuchMethod && !getterCacheEntry.isGetterStub;
- }
-
- InstanceMirror getField(Symbol fieldName) {
- FASTPATH: {
- var cache = _getterCache;
- if (isMissingCache(cache) || isMissingProbe(fieldName)) break FASTPATH;
- // If the [fieldName] has an associated probe function, we can use
- // it to read from the getter cache specific to this [InstanceMirror].
- var getter = JS('', '#.\$p(#)', fieldName, cache);
- if (isUndefined(getter)) break FASTPATH;
- // Call the getter passing the reflectee as the first argument.
- var value = JS('', '#(#)', getter, reflectee);
- // The getter has an associate cache of the last [InstanceMirror]
- // returned to avoid repeated invocations of [reflect]. To validate
- // the cache, we check that the value returned by the getter is the
- // same value as last time.
- if (JS('bool', '# === #.v', value, getter)) {
- return JS('InstanceMirror', '#.m', getter);
- } else {
- var result = reflect(value);
- JS('void', '#.v = #', getter, value);
- JS('void', '#.m = #', getter, result);
- return result;
- }
- }
- return _getFieldSlow(fieldName);
- }
-
- InstanceMirror _getFieldSlow(Symbol fieldName) {
- // First do the slow-case getter invocation. As a side-effect of this,
- // the invocation cache is filled in so we can query it afterwards.
- var result =
- _invoke(fieldName, JSInvocationMirror.GETTER, const [], const {});
- String name = n(fieldName);
- var cacheEntry = JsCache.fetch(_classInvocationCache, name);
- if (cacheEntry.isNoSuchMethod) {
- return result;
- }
-
- // Make sure we have a getter cache in this [InstanceMirror].
- var cache = _getterCache;
- if (isMissingCache(cache)) {
- if ((_getterCache = --cache) != 0) return result;
- cache = _getterCache = JS('=Object', 'Object.create(null)');
- }
-
- // Make sure that symbol [fieldName] has a cache probing function ($p).
- bool useEval = isEvalAllowed();
- if (isMissingProbe(fieldName)) {
- var probe = _newProbeFn(name, useEval);
- JS('void', '#.\$p = #', fieldName, probe);
- }
-
- // Create a new getter function and install it in the cache.
- var mangledName = cacheEntry.mangledName;
- var getter = (cacheEntry.isIntercepted)
- ? _newInterceptedGetterFn(mangledName, useEval)
- : _newGetterFn(mangledName, useEval);
- JS('void', '#[#] = #', cache, name, getter);
-
- // Initialize the last value (v) and last mirror (m) on the
- // newly generated getter to be a sentinel value that is hard
- // to get hold of through user code.
- JS('void', '#.v = #.m = #', getter, getter, cache);
-
- // Return the result of the slow-path getter invocation.
- return result;
- }
-
- _newProbeFn(String id, bool useEval) {
- if (useEval) {
- String body = "return c.$id;";
- return JS('', 'new Function("c", #)', body);
- } else {
- return JS('', '(function(n){return(function(c){return c[n]})})(#)', id);
- }
- }
-
- _newGetterFn(String name, bool useEval) {
- if (!useEval) return _newGetterNoEvalFn(name);
- // We use a comment that associates the generated function with the
- // class of the reflectee. This makes it more likely that the underlying
- // JavaScript engine will only share the generated code for accessors on the
- // same class (through caching of eval'ed code). This makes the
- // generated call to the getter - e.g. o.get$foo() - much more likely
- // to be monomorphic and inlineable.
- String className = JS('String', '#.constructor.name', reflectee);
- String body = "/* $className */ return o.$name();";
- return JS('', 'new Function("o", #)', body);
- }
-
- _newGetterNoEvalFn(n) => JS('',
- '(function(n){return(function(o){return o[n]()})})(#)', n);
-
- _newInterceptedGetterFn(String name, bool useEval) {
- var object = reflectee;
- // It is possible that the interceptor for a given object is the object
- // itself, so it is important not to share the code that captures the
- // interceptor between multiple different instances of [InstanceMirror].
- var interceptor = getInterceptor(object);
- if (!useEval) return _newInterceptGetterNoEvalFn(name, interceptor);
- String className = JS('String', '#.constructor.name', interceptor);
- String functionName = '$className\$$name';
- String body =
- ' function $functionName(o){return i.$name(o)}'
- ' return $functionName;';
- return JS('', '(new Function("i", #))(#)', body, interceptor);
- }
-
- _newInterceptGetterNoEvalFn(n, i) => JS('',
- '(function(n,i){return(function(o){return i[n](o)})})(#,#)', n, i);
-
- delegate(Invocation invocation) {
- return JSInvocationMirror.invokeFromMirror(invocation, reflectee);
- }
-
- operator ==(other) {
- return other is JsInstanceMirror &&
- identical(reflectee, other.reflectee);
- }
-
- int get hashCode {
- // Avoid hash collisions with the reflectee. This constant is in Smi range
- // and happens to be the inner padding from RFC 2104.
- return identityHashCode(reflectee) ^ 0x36363636;
- }
-
- String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}';
-
- // TODO(ahe): Remove this method from the API.
- MirrorSystem get mirrors => currentJsMirrorSystem;
-}
-
-/**
- * ClassMirror for generic classes where the type parameters are bound.
- *
- * [typeArguments] will return a list of the type arguments, in constrast
- * to JsCLassMirror that returns an empty list since it represents original
- * declarations and classes that are not generic.
- */
-class JsTypeBoundClassMirror extends JsDeclarationMirror
- implements ClassMirror {
- final JsClassMirror _class;
-
- /**
- * When instantiated this field will hold a string representing the list of
- * type arguments for the class, i.e. what is inside the outermost angle
- * brackets. Then, when get typeArguments is called the first time, the string
- * is parsed into the actual list of TypeMirrors, and stored in
- * [_cachedTypeArguments]. Due to type substitution of, for instance,
- * superclasses the mangled name of the class and hence this string is needed
- * after [_cachedTypeArguments] has been computed.
- *
- * If an integer is encountered as a type argument, it represents the type
- * variable at the corresponding entry in [emitter.globalMetadata].
- */
- String _typeArguments;
-
- UnmodifiableListView<TypeMirror> _cachedTypeArguments;
- UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
- UnmodifiableMapView<Symbol, DeclarationMirror> _cachedMembers;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
- Map<Symbol, VariableMirror> _cachedVariables;
- Map<Symbol, MethodMirror> _cachedGetters;
- Map<Symbol, MethodMirror> _cachedSetters;
- Map<Symbol, MethodMirror> _cachedMethodsMap;
- List<JsMethodMirror> _cachedMethods;
- ClassMirror _superclass;
- List<ClassMirror> _cachedSuperinterfaces;
- Map<Symbol, MethodMirror> _cachedInstanceMembers;
- Map<Symbol, MethodMirror> _cachedStaticMembers;
-
- JsTypeBoundClassMirror(JsClassMirror originalDeclaration, this._typeArguments)
- : _class = originalDeclaration,
- super(originalDeclaration.simpleName);
-
- String get _prettyName => 'ClassMirror';
-
- String toString() {
- String result = '$_prettyName on ${n(simpleName)}';
- if (typeArguments != null) {
- result = "$result<${typeArguments.join(', ')}>";
- }
- return result;
- }
-
- String get _mangledName {
- for (TypeMirror typeArgument in typeArguments) {
- if (typeArgument != JsMirrorSystem._dynamicType) {
- return '${_class._mangledName}<$_typeArguments>';
- }
- }
- // When all type arguments are dynamic, the canonical representation is to
- // drop them.
- return _class._mangledName;
- }
-
- List<TypeVariableMirror> get typeVariables => _class.typeVariables;
-
- List<TypeMirror> get typeArguments {
- if (_cachedTypeArguments != null) return _cachedTypeArguments;
- List result = new List();
-
- addTypeArgument(String typeArgument) {
- int parsedIndex = int.parse(typeArgument, onError: (_) => -1);
- if (parsedIndex == -1) {
- result.add(reflectClassByMangledName(typeArgument.trim()));
- } else {
- TypeVariable typeVariable = getMetadata(parsedIndex);
- TypeMirror owner = reflectClass(typeVariable.owner);
- TypeVariableMirror typeMirror =
- new JsTypeVariableMirror(typeVariable, owner, parsedIndex);
- result.add(typeMirror);
- }
- }
-
- if (_typeArguments.indexOf('<') == -1) {
- _typeArguments.split(',').forEach((t) => addTypeArgument(t));
- } else {
- int level = 0;
- String currentTypeArgument = '';
-
- for (int i = 0; i < _typeArguments.length; i++) {
- var character = _typeArguments[i];
- if (character == ' ') {
- continue;
- } else if (character == '<') {
- currentTypeArgument += character;
- level++;
- } else if (character == '>') {
- currentTypeArgument += character;
- level--;
- } else if (character == ',') {
- if (level > 0) {
- currentTypeArgument += character;
- } else {
- addTypeArgument(currentTypeArgument);
- currentTypeArgument = '';
- }
- } else {
- currentTypeArgument += character;
- }
- }
- addTypeArgument(currentTypeArgument);
- }
- return _cachedTypeArguments = new UnmodifiableListView(result);
- }
-
- List<JsMethodMirror> get _methods {
- if (_cachedMethods != null) return _cachedMethods;
- return _cachedMethods =_class._getMethodsWithOwner(this);
- }
-
- Map<Symbol, MethodMirror> get __methods {
- if (_cachedMethodsMap != null) return _cachedMethodsMap;
- return _cachedMethodsMap = new UnmodifiableMapView<Symbol, MethodMirror>(
- filterMethods(_methods));
- }
-
- Map<Symbol, MethodMirror> get __constructors {
- if (_cachedConstructors != null) return _cachedConstructors;
- return _cachedConstructors =
- new UnmodifiableMapView<Symbol, MethodMirror>(
- filterConstructors(_methods));
- }
-
- Map<Symbol, MethodMirror> get __getters {
- if (_cachedGetters != null) return _cachedGetters;
- return _cachedGetters = new UnmodifiableMapView<Symbol, MethodMirror>(
- filterGetters(_methods, __variables));
- }
-
- Map<Symbol, MethodMirror> get __setters {
- if (_cachedSetters != null) return _cachedSetters;
- return _cachedSetters = new UnmodifiableMapView<Symbol, MethodMirror>(
- filterSetters(_methods, __variables));
- }
-
- Map<Symbol, VariableMirror> get __variables {
- if (_cachedVariables != null) return _cachedVariables;
- var result = new Map();
- for (JsVariableMirror mirror in _class._getFieldsWithOwner(this)) {
- result[mirror.simpleName] = mirror;
- }
- return _cachedVariables =
- new UnmodifiableMapView<Symbol, VariableMirror>(result);
- }
-
- Map<Symbol, DeclarationMirror> get __members {
- if (_cachedMembers != null) return _cachedMembers;
- return _cachedMembers = new UnmodifiableMapView<Symbol, DeclarationMirror>(
- filterMembers(_methods, __variables));
- }
-
- Map<Symbol, DeclarationMirror> get declarations {
- if (_cachedDeclarations != null) return _cachedDeclarations;
- Map<Symbol, DeclarationMirror> result =
- new Map<Symbol, DeclarationMirror>();
- result.addAll(__members);
- result.addAll(__constructors);
- typeVariables.forEach((tv) => result[tv.simpleName] = tv);
- return _cachedDeclarations =
- new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
- }
-
- Map<Symbol, MethodMirror> get staticMembers {
- if (_cachedStaticMembers == null) {
- var result = new Map<Symbol, MethodMirror>();
- declarations.values.forEach((decl) {
- if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
- result[decl.simpleName] = decl;
- }
- if (decl is VariableMirror && decl.isStatic) {
- var getterName = decl.simpleName;
- result[getterName] = new JsSyntheticAccessor(
- this, getterName, true, true, false, decl);
- if (!decl.isFinal) {
- var setterName = setterSymbol(decl.simpleName);
- result[setterName] = new JsSyntheticAccessor(
- this, setterName, false, true, false, decl);
- }
- }
- });
- _cachedStaticMembers = result;
- }
- return _cachedStaticMembers;
- }
-
- Map<Symbol, MethodMirror> get instanceMembers {
- if (_cachedInstanceMembers == null) {
- var result = new Map<Symbol, MethodMirror>();
- if (superclass != null) {
- result.addAll(superclass.instanceMembers);
- }
- declarations.values.forEach((decl) {
- if (decl is MethodMirror && !decl.isStatic &&
- !decl.isConstructor && !decl.isAbstract) {
- result[decl.simpleName] = decl;
- }
- if (decl is VariableMirror && !decl.isStatic) {
- var getterName = decl.simpleName;
- result[getterName] = new JsSyntheticAccessor(
- this, getterName, true, false, false, decl);
- if (!decl.isFinal) {
- var setterName = setterSymbol(decl.simpleName);
- result[setterName] = new JsSyntheticAccessor(
- this, setterName, false, false, false, decl);
- }
- }
- });
- _cachedInstanceMembers = result;
- }
- return _cachedInstanceMembers;
- }
-
- InstanceMirror setField(Symbol fieldName, Object arg) {
- return _class.setField(fieldName, arg);
- }
-
- InstanceMirror getField(Symbol fieldName) => _class.getField(fieldName);
-
- InstanceMirror newInstance(Symbol constructorName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
- var instance = _class._getInvokedInstance(constructorName,
- positionalArguments,
- namedArguments);
- return reflect(setRuntimeTypeInfo(
- instance, typeArguments.map((t) => t._asRuntimeType()).toList()));
- }
-
- _asRuntimeType() {
- return [_class._jsConstructor].addAll(
- typeArguments.map((t) => t._asRuntimeType()));
- }
-
- JsLibraryMirror get owner => _class.owner;
-
- List<InstanceMirror> get metadata => _class.metadata;
-
- ClassMirror get superclass {
- if (_superclass != null) return _superclass;
-
- var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
- List<int> typeInformation =
- JS('List|Null', '#[#]', typeInformationContainer, _class._mangledName);
- assert(typeInformation != null);
- var type = getType(typeInformation[0]);
- return _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type);
- }
-
- InstanceMirror invoke(Symbol memberName,
- List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) {
- return _class.invoke(memberName, positionalArguments, namedArguments);
- }
-
- bool get isOriginalDeclaration => false;
-
- ClassMirror get originalDeclaration => _class;
-
- List<ClassMirror> get superinterfaces {
- if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces;
- return _cachedSuperinterfaces = _class._getSuperinterfacesWithOwner(this);
- }
-
- bool get isPrivate => _class.isPrivate;
-
- bool get isTopLevel => _class.isTopLevel;
-
- bool get isAbstract => _class.isAbstract;
-
- bool get isEnum => _class.isEnum;
-
- bool isSubclassOf(ClassMirror other) => _class.isSubclassOf(other);
-
- SourceLocation get location => _class.location;
-
- MirrorSystem get mirrors => _class.mirrors;
-
- Symbol get qualifiedName => _class.qualifiedName;
-
- bool get hasReflectedType => true;
-
- Type get reflectedType => createRuntimeType(_mangledName);
-
- Symbol get simpleName => _class.simpleName;
-
- // TODO(ahe): Implement this.
- ClassMirror get mixin => throw new UnimplementedError();
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
-
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-}
-
-class JsSyntheticAccessor implements MethodMirror {
- final DeclarationMirror owner;
- final Symbol simpleName;
- final bool isGetter;
- final bool isStatic;
- final bool isTopLevel;
- final _target; /// The field or type that introduces the synthetic accessor.
-
- JsSyntheticAccessor(this.owner,
- this.simpleName,
- this.isGetter,
- this.isStatic,
- this.isTopLevel,
- this._target);
-
- bool get isSynthetic => true;
- bool get isRegularMethod => false;
- bool get isOperator => false;
- bool get isConstructor => false;
- bool get isConstConstructor => false;
- bool get isGenerativeConstructor => false;
- bool get isFactoryConstructor => false;
- bool get isRedirectingConstructor => false;
- bool get isAbstract => false;
-
- bool get isSetter => !isGetter;
- bool get isPrivate => n(simpleName).startsWith('_');
-
- Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
- Symbol get constructorName => const Symbol('');
-
- TypeMirror get returnType => _target.type;
- List<ParameterMirror> get parameters {
- if (isGetter) return const [];
- return new UnmodifiableListView(
- [new JsSyntheticSetterParameter(this, this._target)]);
- }
-
- List<InstanceMirror> get metadata => const [];
- String get source => null;
- SourceLocation get location => throw new UnimplementedError();
-}
-
-class JsSyntheticSetterParameter implements ParameterMirror {
- final DeclarationMirror owner;
- final VariableMirror _target;
-
- JsSyntheticSetterParameter(this.owner, this._target);
-
- Symbol get simpleName => _target.simpleName;
- Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
- TypeMirror get type => _target.type;
-
- bool get isOptional => false;
- bool get isNamed => false;
- bool get isStatic => false;
- bool get isTopLevel => false;
- bool get isConst => false;
- bool get isFinal => true;
- bool get isPrivate => false;
- bool get hasDefaultValue => false;
- InstanceMirror get defaultValue => null;
- List<InstanceMirror> get metadata => const [];
- SourceLocation get location => throw new UnimplementedError();
-}
-
-class JsClassMirror extends JsTypeMirror with JsObjectMirror
- implements ClassMirror {
- final String _mangledName;
- final _jsConstructor;
- final String _fieldsDescriptor;
- final List _fieldsMetadata;
- final _jsConstructorCache = JsCache.allocate();
- List _metadata;
- ClassMirror _superclass;
- List<JsMethodMirror> _cachedMethods;
- List<VariableMirror> _cachedFields;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedMethodsMap;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
- UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
- UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
- UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
- UnmodifiableMapView<Symbol, DeclarationMirror> _cachedDeclarations;
- UnmodifiableListView<InstanceMirror> _cachedMetadata;
- UnmodifiableListView<ClassMirror> _cachedSuperinterfaces;
- UnmodifiableListView<TypeVariableMirror> _cachedTypeVariables;
- Map<Symbol, MethodMirror> _cachedInstanceMembers;
- Map<Symbol, MethodMirror> _cachedStaticMembers;
-
- // Set as side-effect of accessing JsLibraryMirror.classes.
- JsLibraryMirror _owner;
-
- JsClassMirror(Symbol simpleName,
- this._mangledName,
- this._jsConstructor,
- this._fieldsDescriptor,
- this._fieldsMetadata)
- : super(simpleName);
-
- String get _prettyName => 'ClassMirror';
-
- Map<Symbol, MethodMirror> get __constructors {
- if (_cachedConstructors != null) return _cachedConstructors;
- return _cachedConstructors =
- new UnmodifiableMapView<Symbol, MethodMirror>(
- filterConstructors(_methods));
- }
-
- _asRuntimeType() {
- if (typeVariables.isEmpty) return _jsConstructor;
- var type = [_jsConstructor];
- for (int i = 0; i < typeVariables.length; i ++) {
- type.add(JsMirrorSystem._dynamicType._asRuntimeType);
- }
- return type;
- }
-
- List<JsMethodMirror> _getMethodsWithOwner(DeclarationMirror methodOwner) {
- var prototype = JS('', '#.prototype', _jsConstructor);
- // The prototype might not have been processed yet, so do that now.
- JS('', '#[#]()', prototype,
- JS_GET_NAME(JsGetName.DEFERRED_ACTION_PROPERTY));
- List<String> keys = extractKeys(prototype);
- var result = <JsMethodMirror>[];
- for (String key in keys) {
- if (isReflectiveDataInPrototype(key)) continue;
- String simpleName = mangledNames[key];
- // [simpleName] can be null if [key] represents an implementation
- // detail, for example, a bailout method, or runtime type support.
- // It might also be null if the user has limited what is reified for
- // reflection with metadata.
- if (simpleName == null) continue;
- var function = JS('', '#[#]', prototype, key);
- if (!isOrdinaryReflectableMethod(function)) continue;
- if (isAliasedSuperMethod(function, key)) continue;
- var mirror =
- new JsMethodMirror.fromUnmangledName(
- simpleName, function, false, false);
- result.add(mirror);
- mirror._owner = methodOwner;
- }
-
- var statics = JS_EMBEDDED_GLOBAL('', STATICS);
- keys = extractKeys(JS('', '#[#]', statics, _mangledName));
- for (String mangledName in keys) {
- if (isReflectiveDataInPrototype(mangledName)) continue;
- String unmangledName = mangledName;
- var jsFunction = JS('', '#[#]', owner._globalObject, mangledName);
-
- bool isConstructor = false;
- if (hasReflectableProperty(jsFunction)) {
- String reflectionName =
- JS('String|Null', r'#.$reflectionName', jsFunction);
- if (reflectionName == null) continue;
- isConstructor = reflectionName.startsWith('new ');
- if (isConstructor) {
- reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
- }
- unmangledName = reflectionName;
- } else {
- continue;
- }
- bool isStatic = !isConstructor; // Constructors are not static.
- JsMethodMirror mirror =
- new JsMethodMirror.fromUnmangledName(
- unmangledName, jsFunction, isStatic, isConstructor);
- result.add(mirror);
- mirror._owner = methodOwner;
- }
-
- return result;
- }
-
- List<JsMethodMirror> get _methods {
- if (_cachedMethods != null) return _cachedMethods;
- return _cachedMethods = _getMethodsWithOwner(this);
- }
-
- List<VariableMirror> _getFieldsWithOwner(DeclarationMirror fieldOwner) {
- var result = <VariableMirror>[];
-
- var instanceFieldSpecfication = _fieldsDescriptor.split(';')[1];
- if (_fieldsMetadata != null) {
- instanceFieldSpecfication =
- [instanceFieldSpecfication]..addAll(_fieldsMetadata);
- }
- parseCompactFieldSpecification(
- fieldOwner, instanceFieldSpecfication, false, result);
-
- var statics = JS_EMBEDDED_GLOBAL('', STATICS);
- var staticDescriptor = JS('', '#[#]', statics, _mangledName);
- if (staticDescriptor != null) {
- parseCompactFieldSpecification(
- fieldOwner,
- JS('', '#[#]',
- staticDescriptor,
- JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY)),
- true, result);
- }
- return result;
- }
-
- List<VariableMirror> get _fields {
- if (_cachedFields != null) return _cachedFields;
- return _cachedFields = _getFieldsWithOwner(this);
- }
-
- Map<Symbol, MethodMirror> get __methods {
- if (_cachedMethodsMap != null) return _cachedMethodsMap;
- return _cachedMethodsMap =
- new UnmodifiableMapView<Symbol, MethodMirror>(filterMethods(_methods));
- }
-
- Map<Symbol, MethodMirror> get __getters {
- if (_cachedGetters != null) return _cachedGetters;
- return _cachedGetters = new UnmodifiableMapView<Symbol, MethodMirror>(
- filterGetters(_methods, __variables));
- }
-
- Map<Symbol, MethodMirror> get __setters {
- if (_cachedSetters != null) return _cachedSetters;
- return _cachedSetters = new UnmodifiableMapView<Symbol, MethodMirror>(
- filterSetters(_methods, __variables));
- }
-
- Map<Symbol, VariableMirror> get __variables {
- if (_cachedVariables != null) return _cachedVariables;
- var result = new Map();
- for (JsVariableMirror mirror in _fields) {
- result[mirror.simpleName] = mirror;
- }
- return _cachedVariables =
- new UnmodifiableMapView<Symbol, VariableMirror>(result);
- }
-
- Map<Symbol, Mirror> get __members {
- if (_cachedMembers != null) return _cachedMembers;
- return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(
- filterMembers(_methods, __variables));
- }
-
- Map<Symbol, DeclarationMirror> get declarations {
- if (_cachedDeclarations != null) return _cachedDeclarations;
- var result = new Map<Symbol, DeclarationMirror>();
- addToResult(Symbol key, Mirror value) {
- result[key] = value;
- }
- __members.forEach(addToResult);
- __constructors.forEach(addToResult);
- typeVariables.forEach((tv) => result[tv.simpleName] = tv);
- return _cachedDeclarations =
- new UnmodifiableMapView<Symbol, DeclarationMirror>(result);
- }
-
- Map<Symbol, MethodMirror> get staticMembers {
- if (_cachedStaticMembers == null) {
- var result = new Map<Symbol, MethodMirror>();
- declarations.values.forEach((decl) {
- if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
- result[decl.simpleName] = decl;
- }
- if (decl is VariableMirror && decl.isStatic) {
- var getterName = decl.simpleName;
- result[getterName] = new JsSyntheticAccessor(
- this, getterName, true, true, false, decl);
- if (!decl.isFinal) {
- var setterName = setterSymbol(decl.simpleName);
- result[setterName] = new JsSyntheticAccessor(
- this, setterName, false, true, false, decl);
- }
- }
- });
- _cachedStaticMembers = result;
- }
- return _cachedStaticMembers;
- }
-
- Map<Symbol, MethodMirror> get instanceMembers {
- if (_cachedInstanceMembers == null) {
- var result = new Map<Symbol, MethodMirror>();
- if (superclass != null) {
- result.addAll(superclass.instanceMembers);
- }
- declarations.values.forEach((decl) {
- if (decl is MethodMirror && !decl.isStatic &&
- !decl.isConstructor && !decl.isAbstract) {
- result[decl.simpleName] = decl;
- }
- if (decl is VariableMirror && !decl.isStatic) {
- var getterName = decl.simpleName;
- result[getterName] = new JsSyntheticAccessor(
- this, getterName, true, false, false, decl);
- if (!decl.isFinal) {
- var setterName = setterSymbol(decl.simpleName);
- result[setterName] = new JsSyntheticAccessor(
- this, setterName, false, false, false, decl);
- }
- }
- });
- _cachedInstanceMembers = result;
- }
- return _cachedInstanceMembers;
- }
-
- InstanceMirror setField(Symbol fieldName, Object arg) {
- JsVariableMirror mirror = __variables[fieldName];
- if (mirror != null && mirror.isStatic && !mirror.isFinal) {
- // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so
- // we shouldn't use [JsLibraryMirror._globalObject] here.
- String jsName = mirror._jsName;
- if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
- throw new RuntimeError('Cannot find "$jsName" in current isolate.');
- }
- JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg);
- return reflect(arg);
- }
- Symbol setterName = setterSymbol(fieldName);
- if (mirror == null) {
- JsMethodMirror setter = __setters[setterName];
- if (setter != null) {
- setter._invoke([arg], const {});
- return reflect(arg);
- }
- }
- throw new NoSuchStaticMethodError.method(null, setterName, [arg], null);
- }
-
- bool _staticFieldExists(Symbol fieldName) {
- JsVariableMirror mirror = __variables[fieldName];
- if (mirror != null) return mirror.isStatic;
- JsMethodMirror getter = __getters[fieldName];
- return getter != null && getter.isStatic;
- }
-
- InstanceMirror getField(Symbol fieldName) {
- JsVariableMirror mirror = __variables[fieldName];
- if (mirror != null && mirror.isStatic) {
- String jsName = mirror._jsName;
- // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so
- // we shouldn't use [JsLibraryMirror._globalObject] here.
- if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
- throw new RuntimeError('Cannot find "$jsName" in current isolate.');
- }
- var lazies = JS_EMBEDDED_GLOBAL('', LAZIES);
- if (JS('bool', '# in #', jsName, lazies)) {
- String getterName = JS('String', '#[#]', lazies, jsName);
- return reflect(JS('', '#[#]()', JS_CURRENT_ISOLATE(), getterName));
- } else {
- return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), jsName));
- }
- }
- JsMethodMirror getter = __getters[fieldName];
- if (getter != null && getter.isStatic) {
- return reflect(getter._invoke(const [], const {}));
- }
- // If the fieldName designates a static function we have to return
- // its closure.
- JsMethodMirror method = __methods[fieldName];
- if (method != null && method.isStatic) {
- // We invoke the same getter that Dart code would execute. During
- // initialization we have stored that getter on the function (so that
- // we can find it more easily here).
- var getter = JS("", "#['\$getter']", method._jsFunction);
- if (getter == null) throw new UnimplementedError();
- return reflect(JS("", "#()", getter));
- }
- throw new NoSuchStaticMethodError.method(null, fieldName, null, null);
- }
-
- _getInvokedInstance(Symbol constructorName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
- if (namedArguments != null && !namedArguments.isEmpty) {
- throw new UnsupportedError('Named arguments are not implemented.');
- }
- JsMethodMirror mirror =
- JsCache.fetch(_jsConstructorCache, n(constructorName));
- if (mirror == null) {
- mirror = __constructors.values.firstWhere(
- (m) => m.constructorName == constructorName,
- orElse: () {
- throw new NoSuchStaticMethodError.method(
- null, constructorName, positionalArguments, namedArguments);
- });
- JsCache.update(_jsConstructorCache, n(constructorName), mirror);
- }
- return mirror._invoke(positionalArguments, namedArguments);
- }
-
- InstanceMirror newInstance(Symbol constructorName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
- return reflect(_getInvokedInstance(constructorName,
- positionalArguments,
- namedArguments));
- }
-
- JsLibraryMirror get owner {
- if (_owner == null) {
- for (var list in JsMirrorSystem.librariesByName.values) {
- for (JsLibraryMirror library in list) {
- // This will set _owner field on all classes as a side
- // effect. This gives us a fast path to reflect on a
- // class without parsing reflection data.
- library.__classes;
- }
- }
- if (_owner == null) {
- throw new StateError('Class "${n(simpleName)}" has no owner');
- }
- }
- return _owner;
- }
-
- List<InstanceMirror> get metadata {
- if (_cachedMetadata != null) return _cachedMetadata;
- if (_metadata == null) {
- _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor));
- }
- return _cachedMetadata =
- new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
- }
-
- ClassMirror get superclass {
- if (_superclass == null) {
- var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
- List<int> typeInformation =
- JS('List|Null', '#[#]', typeInformationContainer, _mangledName);
- if (typeInformation != null) {
- var type = getType(typeInformation[0]);
- _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type);
- } else {
- var superclassName = _fieldsDescriptor.split(';')[0].split(':')[0];
- // TODO(zarah): Remove special handing of mixins.
- var mixins = superclassName.split('+');
- if (mixins.length > 1) {
- if (mixins.length != 2) {
- throw new RuntimeError('Strange mixin: $_fieldsDescriptor');
- }
- _superclass = reflectClassByMangledName(mixins[0]);
- } else {
- // Use _superclass == this to represent class with no superclass
- // (Object).
- _superclass = (superclassName == '')
- ? this : reflectClassByMangledName(superclassName);
- }
- }
- }
- return _superclass == this ? null : _superclass;
- }
-
- InstanceMirror invoke(Symbol memberName,
- List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) {
- // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a
- // static method.
-
- if (namedArguments != null && !namedArguments.isEmpty) {
- throw new UnsupportedError('Named arguments are not implemented.');
- }
- JsMethodMirror mirror = __methods[memberName];
-
- if (mirror == null && _staticFieldExists(memberName)) {
- return getField(memberName)
- .invoke(#call, positionalArguments, namedArguments);
- }
- if (mirror == null || !mirror.isStatic) {
- throw new NoSuchStaticMethodError.method(
- null, memberName, positionalArguments, namedArguments);
- }
- if (!mirror.canInvokeReflectively()) {
- throwInvalidReflectionError(n(memberName));
- }
- return reflect(mirror._invoke(positionalArguments, namedArguments));
- }
-
- bool get isOriginalDeclaration => true;
-
- ClassMirror get originalDeclaration => this;
-
- List<ClassMirror> _getSuperinterfacesWithOwner(DeclarationMirror owner) {
- var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION);
- List<int> typeInformation =
- JS('List|Null', '#[#]', typeInformationContainer, _mangledName);
- List<ClassMirror> result = const <ClassMirror>[];
- if (typeInformation != null) {
- ClassMirror lookupType(int i) {
- var type = getType(i);
- return typeMirrorFromRuntimeTypeRepresentation(owner, type);
- }
-
- //We skip the first since it is the supertype.
- result = typeInformation.skip(1).map(lookupType).toList();
- }
-
- return new UnmodifiableListView<ClassMirror>(result);
- }
-
- List<ClassMirror> get superinterfaces {
- if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces;
- return _cachedSuperinterfaces = _getSuperinterfacesWithOwner(this);
- }
-
- List<TypeVariableMirror> get typeVariables {
- if (_cachedTypeVariables != null) return _cachedTypeVariables;
- List result = new List();
- List typeVariables =
- JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor);
- if (typeVariables == null) return result;
- for (int i = 0; i < typeVariables.length; i++) {
- TypeVariable typeVariable = getMetadata(typeVariables[i]);
- result.add(new JsTypeVariableMirror(typeVariable, this,
- typeVariables[i]));
- }
- return _cachedTypeVariables = new UnmodifiableListView(result);
- }
-
- List<TypeMirror> get typeArguments => const <TypeMirror>[];
-
- bool get hasReflectedType => typeVariables.length == 0;
-
- Type get reflectedType {
- if (!hasReflectedType) {
- throw new UnsupportedError(
- "Declarations of generics have no reflected type");
- }
- return createRuntimeType(_mangledName);
- }
-
- // TODO(ahe): Implement this.
- ClassMirror get mixin => throw new UnimplementedError();
-
- bool get isAbstract => throw new UnimplementedError();
-
- bool get isEnum => throw new UnimplementedError();
-
- bool isSubclassOf(ClassMirror other) {
- if (other is! ClassMirror) {
- throw new ArgumentError(other);
- }
- if (other is JsFunctionTypeMirror) {
- return false;
- } if (other is JsClassMirror &&
- JS('bool', '# == #', other._jsConstructor, _jsConstructor)) {
- return true;
- } else if (superclass == null) {
- return false;
- } else {
- return superclass.isSubclassOf(other);
- }
- }
-}
-
-class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
-
- // TODO(ahe): The values in these fields are virtually untested.
- final String _jsName;
- final bool isFinal;
- final bool isStatic;
- final _metadataFunction;
- final DeclarationMirror _owner;
- final int _type;
- List _metadata;
-
- JsVariableMirror(Symbol simpleName,
- this._jsName,
- this._type,
- this.isFinal,
- this.isStatic,
- this._metadataFunction,
- this._owner)
- : super(simpleName);
-
- factory JsVariableMirror.from(String descriptor,
- metadataFunction,
- JsDeclarationMirror owner,
- bool isStatic) {
- List<String> fieldInformation = descriptor.split('-');
- if (fieldInformation.length == 1) {
- // The field is not available for reflection.
- // TODO(ahe): Should return an unreflectable field.
- return null;
- }
-
- String field = fieldInformation[0];
- int length = field.length;
- var code = fieldCode(field.codeUnitAt(length - 1));
- bool isFinal = false;
- if (code == 0) return null; // Inherited field.
- bool hasGetter = (code & 3) != 0;
- bool hasSetter = (code >> 2) != 0;
- isFinal = !hasSetter;
- length--;
- String jsName;
- String accessorName = jsName = field.substring(0, length);
- int divider = field.indexOf(':');
- if (divider > 0) {
- accessorName = accessorName.substring(0, divider);
- jsName = field.substring(divider + 1);
- }
- var unmangledName;
- if (isStatic) {
- unmangledName = mangledGlobalNames[accessorName];
- } else {
- String getterPrefix = JS_GET_NAME(JsGetName.GETTER_PREFIX);
- unmangledName = mangledNames['$getterPrefix$accessorName'];
- }
- if (unmangledName == null) unmangledName = accessorName;
- if (!hasSetter) {
- // TODO(ahe): This is a hack to handle checked setters in checked mode.
- var setterName = s('$unmangledName=');
- for (JsMethodMirror method in owner._methods) {
- if (method.simpleName == setterName) {
- isFinal = false;
- break;
- }
- }
- }
- int type = int.parse(fieldInformation[1], onError: (_) => null);
- return new JsVariableMirror(s(unmangledName),
- jsName,
- type,
- isFinal,
- isStatic,
- metadataFunction,
- owner);
- }
-
- String get _prettyName => 'VariableMirror';
-
- TypeMirror get type {
- return typeMirrorFromRuntimeTypeRepresentation(owner, getType(_type));
- }
-
- DeclarationMirror get owner => _owner;
-
- List<InstanceMirror> get metadata {
- preserveMetadata();
- if (_metadata == null) {
- _metadata = (_metadataFunction == null)
- ? const [] : JS('', '#()', _metadataFunction);
- }
- return _metadata.map(reflect).toList();
- }
-
- static int fieldCode(int code) {
- if (code >= 60 && code <= 64) return code - 59;
- if (code >= 123 && code <= 126) return code - 117;
- if (code >= 37 && code <= 43) return code - 27;
- return 0;
- }
-
- _getField(JsMirror receiver) => receiver._loadField(_jsName);
-
- void _setField(JsMirror receiver, Object arg) {
- if (isFinal) {
- // TODO(floitsch): when the field is non-static we don't want to have
- // a mirror as receiver.
- if (isStatic) {
- throw new NoSuchStaticMethodError.method(
- null, setterSymbol(simpleName), [arg], null);
- }
- throw new NoSuchMethodError(this, setterSymbol(simpleName), [arg], null);
- }
- receiver._storeField(_jsName, arg);
- }
-
- // TODO(ahe): Implement this method.
- bool get isConst => throw new UnimplementedError();
-}
-
-class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
- JsClosureMirror(reflectee)
- : super(reflectee);
-
- MethodMirror get function {
- String cacheName = Primitives.mirrorFunctionCacheName;
- JsMethodMirror cachedFunction;
- // TODO(ahe): Restore caching.
- //= JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
- if (cachedFunction != null) return cachedFunction;
- disableTreeShaking();
- // TODO(ahe): What about optional parameters (named or not).
- String callPrefix = "${JS_GET_NAME(JsGetName.CALL_PREFIX)}\$";
- var extractCallName = JS('', r'''
-function(reflectee) {
- var properties = Object.keys(reflectee.constructor.prototype);
- for (var i = 0; i < properties.length; i++) {
- var property = properties[i];
- if (# == property.substring(0, #) &&
- property[#] >= '0' &&
- property[#] <= '9') return property;
- }
- return null;
-}
-''', callPrefix, callPrefix.length, callPrefix.length, callPrefix.length);
- String callName = JS('String|Null', '#(#)', extractCallName, reflectee);
- if (callName == null) {
- throw new RuntimeError('Cannot find callName on "$reflectee"');
- }
- // TODO(floitsch): What about optional parameters?
- int parameterCount = int.parse(callName.split(r'$')[1]);
- if (reflectee is BoundClosure) {
- var target = BoundClosure.targetOf(reflectee);
- var self = BoundClosure.selfOf(reflectee);
- var name = mangledNames[BoundClosure.nameOf(reflectee)];
- if (name == null) {
- throwInvalidReflectionError(name);
- }
- cachedFunction = new JsMethodMirror.fromUnmangledName(
- name, target, false, false);
- } else {
- bool isStatic = true; // TODO(ahe): Compute isStatic correctly.
- var jsFunction = JS('', '#[#]', reflectee, callName);
- var dummyOptionalParameterCount = 0;
- cachedFunction = new JsMethodMirror(
- s(callName), jsFunction, parameterCount, dummyOptionalParameterCount,
- false, false, isStatic, false, false);
- }
- JS('void', r'#.constructor[#] = #', reflectee, cacheName, cachedFunction);
- return cachedFunction;
- }
-
- InstanceMirror apply(List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
- return reflect(
- Function.apply(reflectee, positionalArguments, namedArguments));
- }
-
- String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'";
-
- // TODO(ahe): Implement this method.
- String get source => throw new UnimplementedError();
-}
-
-class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
- final _jsFunction;
- final int _requiredParameterCount;
- final int _optionalParameterCount;
- final bool isGetter;
- final bool isSetter;
- final bool isStatic;
- final bool isConstructor;
- final bool isOperator;
- DeclarationMirror _owner;
- List _metadata;
- TypeMirror _returnType;
- UnmodifiableListView<ParameterMirror> _parameters;
-
- JsMethodMirror(Symbol simpleName,
- this._jsFunction,
- this._requiredParameterCount,
- this._optionalParameterCount,
- this.isGetter,
- this.isSetter,
- this.isStatic,
- this.isConstructor,
- this.isOperator)
- : super(simpleName);
-
- factory JsMethodMirror.fromUnmangledName(String name,
- jsFunction,
- bool isStatic,
- bool isConstructor) {
- List<String> info = name.split(':');
- name = info[0];
- bool isOperator = isOperatorName(name);
- bool isSetter = !isOperator && name.endsWith('=');
- int requiredParameterCount = 0;
- int optionalParameterCount = 0;
- bool isGetter = false;
- if (info.length == 1) {
- if (isSetter) {
- requiredParameterCount = 1;
- } else {
- isGetter = true;
- requiredParameterCount = 0;
- }
- } else {
- ReflectionInfo reflectionInfo = new ReflectionInfo(jsFunction);
- requiredParameterCount = reflectionInfo.requiredParameterCount;
- optionalParameterCount = reflectionInfo.optionalParameterCount;
- assert(int.parse(info[1]) == requiredParameterCount
- + optionalParameterCount);
- }
- return new JsMethodMirror(
- s(name), jsFunction, requiredParameterCount, optionalParameterCount,
- isGetter, isSetter, isStatic, isConstructor, isOperator);
- }
-
- String get _prettyName => 'MethodMirror';
-
- int get _parameterCount => _requiredParameterCount + _optionalParameterCount;
-
- List<ParameterMirror> get parameters {
- if (_parameters != null) return _parameters;
- metadata; // Compute _parameters as a side-effect of extracting metadata.
- return _parameters;
- }
-
- bool canInvokeReflectively() {
- return hasReflectableProperty(_jsFunction);
- }
-
- DeclarationMirror get owner => _owner;
-
- TypeMirror get returnType {
- metadata; // Compute _returnType as a side-effect of extracting metadata.
- return _returnType;
- }
-
- List<InstanceMirror> get metadata {
- if (_metadata == null) {
- var raw = extractMetadata(_jsFunction);
- var formals = new List(_parameterCount);
- ReflectionInfo info = new ReflectionInfo(_jsFunction);
- if (info != null) {
- assert(_parameterCount
- == info.requiredParameterCount + info.optionalParameterCount);
- var functionType = info.functionType;
- var type;
- if (functionType is int) {
- type = new JsFunctionTypeMirror(info.computeFunctionRti(null), this);
- assert(_parameterCount == type.parameters.length);
- } else if (isTopLevel) {
- type = new JsFunctionTypeMirror(info.computeFunctionRti(null), owner);
- } else {
- TypeMirror ownerType = owner;
- JsClassMirror ownerClass = ownerType.originalDeclaration;
- type = new JsFunctionTypeMirror(
- info.computeFunctionRti(ownerClass._jsConstructor),
- owner);
- }
- // Constructors aren't reified with their return type.
- if (isConstructor) {
- _returnType = owner;
- } else {
- _returnType = type.returnType;
- }
- int i = 0;
- bool isNamed = info.areOptionalParametersNamed;
- for (JsParameterMirror parameter in type.parameters) {
- var name = info.parameterName(i);
- List<int> annotations = info.parameterMetadataAnnotations(i);
- var p;
- if (i < info.requiredParameterCount) {
- p = new JsParameterMirror(name, this, parameter._type,
- metadataList: annotations);
- } else {
- var defaultValue = info.defaultValue(i);
- p = new JsParameterMirror(
- name, this, parameter._type, metadataList: annotations,
- isOptional: true, isNamed: isNamed, defaultValue: defaultValue);
- }
- formals[i++] = p;
- }
- }
- _parameters = new UnmodifiableListView<ParameterMirror>(formals);
- _metadata = new UnmodifiableListView(raw.map(reflect));
- }
- return _metadata;
- }
-
- Symbol get constructorName {
- // TODO(ahe): I believe it is more appropriate to throw an exception or
- // return null.
- if (!isConstructor) return const Symbol('');
- String name = n(simpleName);
- int index = name.indexOf('.');
- if (index == -1) return const Symbol('');
- return s(name.substring(index + 1));
- }
-
- _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
- if (namedArguments != null && !namedArguments.isEmpty) {
- throw new UnsupportedError('Named arguments are not implemented.');
- }
- if (!isStatic && !isConstructor) {
- throw new RuntimeError('Cannot invoke instance method without receiver.');
- }
- int positionalLength = positionalArguments.length;
- if (positionalLength < _requiredParameterCount ||
- positionalLength > _parameterCount ||
- _jsFunction == null) {
- // TODO(ahe): What receiver to use?
- throw new NoSuchMethodError(
- owner, simpleName, positionalArguments, namedArguments);
- }
- if (positionalLength < _parameterCount) {
- // Fill up with default values.
- // Make a copy so we don't modify the input.
- positionalArguments = positionalArguments.toList();
- for (int i = positionalLength; i < parameters.length; i++) {
- JsParameterMirror parameter = parameters[i];
- positionalArguments.add(parameter.defaultValue.reflectee);
- }
- }
- // Using JS_CURRENT_ISOLATE() ('$') here is actually correct, although
- // _jsFunction may not be a property of '$', most static functions do not
- // care who their receiver is. But to lazy getters, it is important that
- // 'this' is '$'.
- return JS('', r'#.apply(#, #)', _jsFunction, JS_CURRENT_ISOLATE(),
- 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, setterSymbol(simpleName), [], null);
- }
- }
-
- // Abstract methods are tree-shaken away.
- bool get isAbstract => false;
-
- // TODO(ahe, 14633): This might not be true for all cases.
- bool get isSynthetic => false;
-
- // TODO(ahe): Test this.
- bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;
-
- // TODO(ahe): Implement this method.
- bool get isConstConstructor => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- bool get isGenerativeConstructor => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- bool get isRedirectingConstructor => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- bool get isFactoryConstructor => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- String get source => throw new UnimplementedError();
-}
-
-class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
- final DeclarationMirror owner;
- // A JS object representing the type.
- final _type;
-
- final bool isOptional;
-
- final bool isNamed;
-
- final int _defaultValue;
-
- final List<int> metadataList;
-
- JsParameterMirror(String unmangledName,
- this.owner,
- this._type,
- {this.metadataList: const <int>[],
- this.isOptional: false,
- this.isNamed: false,
- defaultValue})
- : _defaultValue = defaultValue,
- super(s(unmangledName));
-
- String get _prettyName => 'ParameterMirror';
-
- TypeMirror get type {
- return typeMirrorFromRuntimeTypeRepresentation(owner, _type);
- }
-
- // Only true for static fields, never for a parameter.
- bool get isStatic => false;
-
- // TODO(ahe): Implement this.
- bool get isFinal => false;
-
- // TODO(ahe): Implement this.
- bool get isConst => false;
-
- bool get hasDefaultValue => _defaultValue != null;
-
- get defaultValue {
- return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null;
- }
-
- List<InstanceMirror> get metadata {
- preserveMetadata();
- return metadataList.map((int i) => reflect(getMetadata(i))).toList();
- }
-}
-
-class JsTypedefMirror extends JsDeclarationMirror implements TypedefMirror {
- final String _mangledName;
- JsFunctionTypeMirror referent;
-
- JsTypedefMirror(Symbol simpleName, this._mangledName, _typeData)
- : super(simpleName) {
- referent = new JsFunctionTypeMirror(_typeData, this);
- }
-
- JsFunctionTypeMirror get value => referent;
-
- String get _prettyName => 'TypedefMirror';
-
- bool get hasReflectedType => throw new UnimplementedError();
-
- Type get reflectedType => createRuntimeType(_mangledName);
-
- // TODO(floitsch): Implement this method.
- List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
-
- // TODO(floitsch): Implement this method.
- List<TypeMirror> get typeArguments => throw new UnimplementedError();
-
- bool get isOriginalDeclaration => true;
-
- TypeMirror get originalDeclaration => this;
-
- // TODO(floitsch): Implement this method.
- DeclarationMirror get owner => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- List<InstanceMirror> get metadata => throw new UnimplementedError();
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-}
-
-// TODO(ahe): Remove this class when API is updated.
-class BrokenClassMirror {
- bool get hasReflectedType => throw new UnimplementedError();
- Type get reflectedType => throw new UnimplementedError();
- ClassMirror get superclass => throw new UnimplementedError();
- List<ClassMirror> get superinterfaces => throw new UnimplementedError();
- Map<Symbol, DeclarationMirror> get declarations
- => throw new UnimplementedError();
- Map<Symbol, MethodMirror> get instanceMembers
- => throw new UnimplementedError();
- Map<Symbol, MethodMirror> get staticMembers => throw new UnimplementedError();
- ClassMirror get mixin => throw new UnimplementedError();
- InstanceMirror newInstance(
- Symbol constructorName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) => throw new UnimplementedError();
- InstanceMirror invoke(Symbol memberName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments])
- => throw new UnimplementedError();
- InstanceMirror getField(Symbol fieldName) => throw new UnimplementedError();
- InstanceMirror setField(Symbol fieldName, Object value)
- => throw new UnimplementedError();
- List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
- List<TypeMirror> get typeArguments => throw new UnimplementedError();
- TypeMirror get originalDeclaration => throw new UnimplementedError();
- Symbol get simpleName => throw new UnimplementedError();
- Symbol get qualifiedName => throw new UnimplementedError();
- bool get isPrivate => throw new UnimplementedError();
- bool get isTopLevel => throw new UnimplementedError();
- SourceLocation get location => throw new UnimplementedError();
- List<InstanceMirror> get metadata => throw new UnimplementedError();
-}
-
-class JsFunctionTypeMirror extends BrokenClassMirror
- implements FunctionTypeMirror {
- final _typeData;
- String _cachedToString;
- TypeMirror _cachedReturnType;
- UnmodifiableListView<ParameterMirror> _cachedParameters;
- DeclarationMirror owner;
-
- JsFunctionTypeMirror(this._typeData, this.owner);
-
- bool get _hasReturnType {
- return JS('bool', '# in #',
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG), _typeData);
- }
-
- get _returnType {
- return JS('', '#[#]', _typeData,
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG));
- }
-
- bool get _isVoid {
- return JS('bool', '!!#[#]', _typeData,
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG));
- }
-
- bool get _hasArguments {
- return JS('bool', '# in #',
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG),
- _typeData);
- }
- List get _arguments {
- return JS('JSExtendableArray', '#[#]',
- _typeData,
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG));
- }
-
- bool get _hasOptionalArguments {
- return JS('bool', '# in #',
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG),
- _typeData);
- }
- List get _optionalArguments {
- return JS('JSExtendableArray', '#[#]',
- _typeData,
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG));
- }
-
- bool get _hasNamedArguments {
- return JS('bool', '# in #',
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG),
- _typeData);
- }
- get _namedArguments {
- return JS('=Object', '#[#]',
- _typeData,
- JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG));
- }
-
- bool get isOriginalDeclaration => true;
-
- bool get isAbstract => false;
-
- bool get isEnum => false;
-
- TypeMirror get returnType {
- if (_cachedReturnType != null) return _cachedReturnType;
- if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType;
- if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType;
- return _cachedReturnType =
- typeMirrorFromRuntimeTypeRepresentation(owner, _returnType);
- }
-
- List<ParameterMirror> get parameters {
- if (_cachedParameters != null) return _cachedParameters;
- List result = [];
- int parameterCount = 0;
- if (_hasArguments) {
- for (var type in _arguments) {
- result.add(
- new JsParameterMirror('argument${parameterCount++}', this, type));
- }
- }
- if (_hasOptionalArguments) {
- for (var type in _optionalArguments) {
- result.add(
- new JsParameterMirror('argument${parameterCount++}', this, type));
- }
- }
- if (_hasNamedArguments) {
- for (var name in extractKeys(_namedArguments)) {
- var type = JS('', '#[#]', _namedArguments, name);
- result.add(new JsParameterMirror(name, this, type));
- }
- }
- return _cachedParameters = new UnmodifiableListView<ParameterMirror>(
- result);
- }
-
- String _unmangleIfPreserved(String mangled) {
- String result = unmangleGlobalNameIfPreservedAnyways(mangled);
- if (result != null) return result;
- return mangled;
- }
-
- String toString() {
- if (_cachedToString != null) return _cachedToString;
- var s = "FunctionTypeMirror on '(";
- var sep = '';
- if (_hasArguments) {
- for (var argument in _arguments) {
- s += sep;
- s += _unmangleIfPreserved(runtimeTypeToString(argument));
- sep = ', ';
- }
- }
- if (_hasOptionalArguments) {
- s += '$sep[';
- sep = '';
- for (var argument in _optionalArguments) {
- s += sep;
- s += _unmangleIfPreserved(runtimeTypeToString(argument));
- sep = ', ';
- }
- s += ']';
- }
- if (_hasNamedArguments) {
- s += '$sep{';
- sep = '';
- for (var name in extractKeys(_namedArguments)) {
- s += sep;
- s += '$name: ';
- s += _unmangleIfPreserved(
- runtimeTypeToString(JS('', '#[#]', _namedArguments, name)));
- sep = ', ';
- }
- s += '}';
- }
- s += ') -> ';
- if (_isVoid) {
- s += 'void';
- } else if (_hasReturnType) {
- s += _unmangleIfPreserved(runtimeTypeToString(_returnType));
- } else {
- s += 'dynamic';
- }
- return _cachedToString = "$s'";
- }
-
- bool isSubclassOf(ClassMirror other) => false;
-
- bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError();
-
- bool isAssignableTo(TypeMirror other) => throw new UnimplementedError();
-
- // TODO(ahe): Implement this method.
- MethodMirror get callMethod => throw new UnimplementedError();
-}
-
-int findTypeVariableIndex(List<TypeVariableMirror> typeVariables, String name) {
- for (int i = 0; i < typeVariables.length; i++) {
- if (typeVariables[i].simpleName == s(name)) {
- return i;
- }
- }
- throw new ArgumentError('Type variable not present in list.');
-}
-
-TypeMirror typeMirrorFromRuntimeTypeRepresentation(
- DeclarationMirror owner,
- var /*int|List|JsFunction|TypeImpl*/ type) {
- // TODO(ahe): This method might benefit from using convertRtiToRuntimeType
- // instead of working on strings.
- ClassMirror ownerClass;
- DeclarationMirror context = owner;
- while (context != null) {
- if (context is ClassMirror) {
- ownerClass = context;
- break;
- }
- // TODO(ahe): Get type parameters and arguments from typedefs.
- if (context is TypedefMirror) break;
- context = context.owner;
- }
-
- String representation;
- if (type == null) {
- return JsMirrorSystem._dynamicType;
- } else if (type is TypeImpl) {
- return reflectType(type);
- } else if (ownerClass == null) {
- representation = runtimeTypeToString(type);
- } else if (ownerClass.isOriginalDeclaration) {
- if (type is num) {
- // [type] represents a type variable so in the context of an original
- // declaration the corresponding type variable should be returned.
- TypeVariable typeVariable = getMetadata(type);
- List<TypeVariableMirror> typeVariables = ownerClass.typeVariables;
- int index = findTypeVariableIndex(typeVariables, typeVariable.name);
- return typeVariables[index];
- } else {
- // Nested type variables will be retrieved lazily (the integer
- // representation is kept in the string) so they are not processed here.
- representation = runtimeTypeToString(type);
- }
- } else {
- TypeMirror getTypeArgument(int index) {
- TypeVariable typeVariable = getMetadata(index);
- int variableIndex =
- findTypeVariableIndex(ownerClass.typeVariables, typeVariable.name);
- return ownerClass.typeArguments[variableIndex];
- }
-
- if (type is num) {
- // [type] represents a type variable used as type argument for example
- // the type argument of Bar: class Foo<T> extends Bar<T> {}
- TypeMirror typeArgument = getTypeArgument(type);
- if (typeArgument is JsTypeVariableMirror)
- return typeArgument;
- }
- String substituteTypeVariable(int index) {
- var typeArgument = getTypeArgument(index);
- if (typeArgument is JsTypeVariableMirror) {
- return '${typeArgument._metadataIndex}';
- }
- if (typeArgument is! JsClassMirror &&
- typeArgument is! JsTypeBoundClassMirror) {
- if (typeArgument == JsMirrorSystem._dynamicType) {
- return 'dynamic';
- } else if (typeArgument == JsMirrorSystem._voidType) {
- return 'void';
- } else {
- // TODO(ahe): This case shouldn't happen.
- return 'dynamic';
- }
- }
- return typeArgument._mangledName;
- }
- representation =
- runtimeTypeToString(type, onTypeVariable: substituteTypeVariable);
- }
- if (representation != null) {
- return reflectClassByMangledName(
- getMangledTypeName(createRuntimeType(representation)));
- }
- String typedefPropertyName = JS_GET_NAME(JsGetName.TYPEDEF_TAG);
- if (type != null && JS('', '#[#]', type, typedefPropertyName) != null) {
- return typeMirrorFromRuntimeTypeRepresentation(
- owner, JS('', '#[#]', type, typedefPropertyName));
- } else if (type != null && isDartFunctionType(type)) {
- return new JsFunctionTypeMirror(type, owner);
- }
- return reflectClass(Function);
-}
-
-Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
- if (owner == null) return simpleName;
- String ownerName = n(owner.qualifiedName);
- return s('$ownerName.${n(simpleName)}');
-}
-
-List extractMetadata(victim) {
- preserveMetadata();
- var metadataFunction;
- if (JS('bool', 'Object.prototype.hasOwnProperty.call(#, "@")', victim)) {
- metadataFunction = JS('', '#["@"]', victim);
- }
- if (metadataFunction != null) return JS('', '#()', metadataFunction);
- if (JS('bool', 'typeof # != "function"', victim)) return const [];
- if (JS('bool', '# in #', r'$metadataIndex', victim)) {
- return JSArray.markFixedList(
- JS('JSExtendableArray',
- r'#.$reflectionInfo.splice(#.$metadataIndex)', victim, victim))
- .map((int i) => getMetadata(i)).toList();
- }
- return const [];
-}
-
-void parseCompactFieldSpecification(
- JsDeclarationMirror owner,
- fieldSpecification,
- bool isStatic,
- List<Mirror> result) {
- List fieldsMetadata = null;
- List<String> fields;
- if (fieldSpecification is List) {
- fields = splitFields(fieldSpecification[0], ',');
- fieldsMetadata = fieldSpecification.sublist(1);
- } else if (fieldSpecification is String) {
- fields = splitFields(fieldSpecification, ',');
- } else {
- fields = [];
- }
- int fieldNumber = 0;
- for (String field in fields) {
- 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);
-}
-
-bool isOperatorName(String name) {
- switch (name) {
- case '==':
- case '[]':
- case '*':
- case '/':
- case '%':
- case '~/':
- case '+':
- case '<<':
- case '>>':
- case '>=':
- case '>':
- case '<=':
- case '<':
- case '&':
- case '^':
- case '|':
- case '-':
- case 'unary-':
- case '[]=':
- case '~':
- return true;
- default:
- return false;
- }
-}
-
-/// Returns true if the key represent ancillary reflection data, that is, not a
-/// method.
-bool isReflectiveDataInPrototype(String key) {
- if (key == JS_GET_NAME(JsGetName.CLASS_DESCRIPTOR_PROPERTY) ||
- key == METHODS_WITH_OPTIONAL_ARGUMENTS) {
- return true;
- }
- String firstChar = key[0];
- return firstChar == '*' || firstChar == '+';
-}
-
-/// Returns `true` if [jsFunction] is an ordinary reflectable method and
-/// not a (potentially reflectable) stub or otherwise non-reflectable method.
-bool isOrdinaryReflectableMethod(var jsFunction) {
- return JS('bool', r'#.$reflectable === 1', jsFunction);
-}
-
-/// Returns true if [key] is only an aliased entry for [function] in the
-/// prototype.
-bool isAliasedSuperMethod(var jsFunction, String key) {
- var stubName = JS('String|Null', r'#.$stubName', jsFunction);
- return stubName != null && key != stubName;
-}
-
-class NoSuchStaticMethodError extends Error implements NoSuchMethodError {
- static const int MISSING_CONSTRUCTOR = 0;
- static const int MISSING_METHOD = 1;
- final ClassMirror _cls;
- final Symbol _name;
- final List _positionalArguments;
- final Map<Symbol, dynamic> _namedArguments;
- final int _kind;
-
- NoSuchStaticMethodError.missingConstructor(
- this._cls,
- this._name,
- this._positionalArguments,
- this._namedArguments)
- : _kind = MISSING_CONSTRUCTOR;
-
- /// If the given class is `null` the static method/getter/setter is top-level.
- NoSuchStaticMethodError.method(
- this._cls,
- this._name,
- this._positionalArguments,
- this._namedArguments)
- : _kind = MISSING_METHOD;
-
- String toString() {
- // TODO(floitsch): show arguments.
- switch(_kind) {
- case MISSING_CONSTRUCTOR:
- return
- "NoSuchMethodError: No constructor named '${n(_name)}' in class"
- " '${n(_cls.qualifiedName)}'.";
- case MISSING_METHOD:
- if (_cls == null) {
- return "NoSuchMethodError: No top-level method named '${n(_name)}'.";
- }
- return "NoSuchMethodError: No static method named '${n(_name)}' in"
- " class '${n(_cls.qualifiedName)}'";
- default:
- return 'NoSuchMethodError';
- }
- }
-}
-
-Symbol getSymbol(String name, LibraryMirror library) {
- if (_isPublicSymbol(name)) {
- return new _symbol_dev.Symbol.validated(name);
- }
- if (library == null) {
- throw new ArgumentError(
- "Library required for private symbol name: $name");
- }
- if (!_symbol_dev.Symbol.isValidSymbol(name)) {
- throw new ArgumentError("Not a valid symbol name: $name");
- }
- throw new UnimplementedError(
- "MirrorSystem.getSymbol not implemented for private names");
-}
-
-bool _isPublicSymbol(String name) {
- // A symbol is public if it doesn't start with '_' and it doesn't
- // have a part (following a '.') that starts with '_'.
- const int UNDERSCORE = 0x5f;
- if (name.isEmpty) return true;
- int index = -1;
- do {
- if (name.codeUnitAt(index + 1) == UNDERSCORE) return false;
- index = name.indexOf('.', index + 1);
- } while (index >= 0 && index + 1 < name.length);
- return true;
-}

Powered by Google App Engine
This is Rietveld 408576698