| Index: dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| diff --git a/dart/sdk/lib/_internal/lib/js_mirrors.dart b/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| index 0cb1720955cf53e019aea8cf9e8ddf8d3ff6196b..b1fb4c4f94ae2a48e2be001865a4e0549a96756d 100644
|
| --- a/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| +++ b/dart/sdk/lib/_internal/lib/js_mirrors.dart
|
| @@ -5,10 +5,7 @@
|
| library dart._js_mirrors;
|
|
|
| import 'dart:async';
|
| -
|
| -import 'dart:collection' show
|
| - UnmodifiableListView;
|
| -
|
| +import 'dart:collection' show UnmodifiableListView;
|
| import 'dart:mirrors';
|
|
|
| import 'dart:_foreign_helper' show
|
| @@ -16,9 +13,7 @@ import 'dart:_foreign_helper' show
|
| JS_CURRENT_ISOLATE,
|
| JS_CURRENT_ISOLATE_CONTEXT,
|
| JS_GET_NAME;
|
| -
|
| import 'dart:_collection-dev' as _symbol_dev;
|
| -
|
| import 'dart:_js_helper' show
|
| BoundClosure,
|
| Closure,
|
| @@ -26,25 +21,17 @@ import 'dart:_js_helper' show
|
| JsCache,
|
| Null,
|
| Primitives,
|
| - ReflectionInfo,
|
| RuntimeError,
|
| - TypeVariable,
|
| - UnimplementedNoSuchMethodError,
|
| createRuntimeType,
|
| createUnmangledInvocationMirror,
|
| getMangledTypeName,
|
| - getMetadata,
|
| + throwInvalidReflectionError,
|
| hasReflectableProperty,
|
| runtimeTypeToString,
|
| - setRuntimeTypeInfo,
|
| - throwInvalidReflectionError;
|
| -
|
| + TypeVariable;
|
| import 'dart:_interceptors' show
|
| Interceptor,
|
| - JSArray,
|
| - JSExtendableArray,
|
| - getInterceptor;
|
| -
|
| + JSExtendableArray;
|
| import 'dart:_js_names';
|
|
|
| const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments';
|
| @@ -784,34 +771,35 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| String name = n(memberName);
|
| String reflectiveName;
|
| if (namedArguments != null && !namedArguments.isEmpty) {
|
| - var interceptor = getInterceptor(reflectee);
|
| -
|
| - var jsFunction = JS('', '#[# + "*"]', interceptor, name);
|
| - 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) {
|
| + var methodsWithOptionalArguments =
|
| + JS('=Object', '#.\$methodsWithOptionalArguments', reflectee);
|
| + String mangledName =
|
| + JS('String|Null', '#[#]', methodsWithOptionalArguments, '*$name');
|
| + if (mangledName == null) {
|
| // TODO(ahe): Invoke noSuchMethod.
|
| throw new UnimplementedNoSuchMethodError(
|
| 'Invoking noSuchMethod with named arguments not implemented');
|
| }
|
| -
|
| + var defaultValueIndices =
|
| + JS('List|Null', '#[#].\$defaultValues', reflectee, mangledName);
|
| + var defaultValues =
|
| + defaultValueIndices.map((int i) => getMetadata(i))
|
| + .iterator;
|
| + var defaultArguments = new Map();
|
| + reflectiveName = mangledNames[mangledName];
|
| + var reflectiveNames = reflectiveName.split(':');
|
| + int requiredPositionalArgumentCount =
|
| + int.parse(reflectiveNames.elementAt(1));
|
| positionalArguments = new List.from(positionalArguments);
|
| // Check the number of positional arguments is valid.
|
| - if (info.requiredParameterCount != positionalArguments.length) {
|
| + if (requiredPositionalArgumentCount != 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;
|
| + for (String parameter in reflectiveNames.skip(3)) {
|
| + defaultValues.moveNext();
|
| + defaultArguments[parameter] = defaultValues.current;
|
| }
|
| namedArguments.forEach((Symbol symbol, value) {
|
| String parameter = n(symbol);
|
| @@ -825,9 +813,6 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| }
|
| });
|
| positionalArguments.addAll(defaultArguments.values);
|
| - // TODO(ahe): Handle intercepted methods.
|
| - return reflect(
|
| - JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments));
|
| } else {
|
| reflectiveName =
|
| JS('String', '# + ":" + # + ":0"', name, positionalArguments.length);
|
| @@ -1216,23 +1201,25 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| }
|
|
|
| keys = extractKeys(JS('', 'init.statics[#]', _mangledName));
|
| - for (String mangledName in keys) {
|
| + int length = keys.length;
|
| + for (int i = 0; i < length; i++) {
|
| + String mangledName = keys[i];
|
| 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'$', '.');
|
| + if (i + 1 < length) {
|
| + String reflectionName = keys[i + 1];
|
| + if (reflectionName.startsWith('+')) {
|
| + i++;
|
| + reflectionName = reflectionName.substring(1);
|
| + 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 =
|
| @@ -1370,7 +1357,7 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| (m) => m.constructorName == constructorName,
|
| orElse: () {
|
| // TODO(ahe): What receiver to use?
|
| - throw new NoSuchStaticMethodError.missingConstructor(
|
| + throw new NoSuchMethodError(
|
| this, constructorName, positionalArguments, namedArguments);
|
| });
|
| JsCache.update(_jsConstructorCache, n(constructorName), mirror);
|
| @@ -1630,9 +1617,8 @@ class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
|
|
|
| MethodMirror get function {
|
| String cacheName = Primitives.mirrorFunctionCacheName;
|
| - JsMethodMirror cachedFunction;
|
| - // TODO(ahe): Restore caching.
|
| - //= JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
|
| + JsMethodMirror cachedFunction =
|
| + JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
|
| if (cachedFunction != null) return cachedFunction;
|
| disableTreeShaking();
|
| // TODO(ahe): What about optional parameters (named or not).
|
| @@ -1699,7 +1685,7 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
|
| final bool isOperator;
|
| DeclarationMirror _owner;
|
| List _metadata;
|
| - TypeMirror _returnType;
|
| + var _returnType;
|
| UnmodifiableListView<ParameterMirror> _parameters;
|
|
|
| JsMethodMirror(Symbol simpleName,
|
| @@ -1755,49 +1741,26 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
|
|
|
| TypeMirror get returnType {
|
| metadata; // Compute _returnType as a side-effect of extracting metadata.
|
| - return _returnType;
|
| + return typeMirrorFromRuntimeTypeRepresentation(owner, _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 {
|
| - TypeMirror ownerType = owner;
|
| - JsClassMirror ownerClass = ownerType.originalDeclaration;
|
| - type = new JsFunctionTypeMirror(
|
| - info.computeFunctionRti(ownerClass._jsConstructorOrInterceptor),
|
| - owner);
|
| + if (!raw.isEmpty) {
|
| + _returnType = raw[0];
|
| + int parameterLength = 1 + _parameterCount * 2;
|
| + int formalsCount = 0;
|
| + for (int i = 1; i < parameterLength; i += 2) {
|
| + var name = raw[i];
|
| + var type = raw[i + 1];
|
| + formals[formalsCount++] = new JsParameterMirror(name, this, type);
|
| }
|
| - // 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);
|
| - var p;
|
| - if (i < info.requiredParameterCount) {
|
| - p = new JsParameterMirror(name, this, parameter._type);
|
| - } else {
|
| - var defaultValue = info.defaultValue(i);
|
| - p = new JsParameterMirror(
|
| - name, this, parameter._type,
|
| - isOptional: true, isNamed: isNamed, defaultValue: defaultValue);
|
| - }
|
| - formals[i++] = p;
|
| + raw = raw.sublist(parameterLength);
|
| + } else {
|
| + for (int i = 0; i < _parameterCount; i++) {
|
| + formals[i] = new JsParameterMirror('argument$i', this, null);
|
| }
|
| }
|
| _parameters = new UnmodifiableListView<ParameterMirror>(formals);
|
| @@ -1880,20 +1843,8 @@ class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
|
| // A JS object representing the type.
|
| final _type;
|
|
|
| - final bool isOptional;
|
| -
|
| - final bool isNamed;
|
| -
|
| - final int _defaultValue;
|
| -
|
| - JsParameterMirror(String unmangledName,
|
| - this.owner,
|
| - this._type,
|
| - {this.isOptional: false,
|
| - this.isNamed: false,
|
| - defaultValue})
|
| - : _defaultValue = defaultValue,
|
| - super(s(unmangledName));
|
| + JsParameterMirror(String unmangledName, this.owner, this._type)
|
| + : super(s(unmangledName));
|
|
|
| String get _prettyName => 'ParameterMirror';
|
|
|
| @@ -1907,14 +1858,19 @@ class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
|
| // TODO(ahe): Implement this.
|
| bool get isFinal => false;
|
|
|
| - // TODO(ahe): Implement this.
|
| bool get isConst => false;
|
|
|
| - bool get hasDefaultValue => _defaultValue != null;
|
| + // TODO(ahe): Implement this.
|
| + bool get isOptional => false;
|
|
|
| - get defaultValue {
|
| - return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null;
|
| - }
|
| + // TODO(ahe): Implement this.
|
| + bool get isNamed => false;
|
| +
|
| + // TODO(ahe): Implement this.
|
| + bool get hasDefaultValue => false;
|
| +
|
| + // TODO(ahe): Implement this.
|
| + get defaultValue => null;
|
|
|
| // TODO(ahe): Implement this.
|
| List<InstanceMirror> get metadata => throw new UnimplementedError();
|
| @@ -2017,7 +1973,7 @@ class JsFunctionTypeMirror extends BrokenClassMirror
|
| if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType;
|
| if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType;
|
| return _cachedReturnType =
|
| - typeMirrorFromRuntimeTypeRepresentation(owner, _returnType);
|
| + typeMirrorFromRuntimeTypeRepresentation(this, _returnType);
|
| }
|
|
|
| List<ParameterMirror> get parameters {
|
| @@ -2102,25 +2058,23 @@ int findTypeVariableIndex(List<TypeVariableMirror> typeVariables, String name) {
|
| throw new ArgumentError('Type variable not present in list.');
|
| }
|
|
|
| +getMetadata(int index) => JS('', 'init.metadata[#]', index);
|
| +
|
| TypeMirror typeMirrorFromRuntimeTypeRepresentation(
|
| DeclarationMirror owner,
|
| var /*int|List|JsFunction*/ type) {
|
| - // TODO(ahe): This method might benefit from using convertRtiToRuntimeType
|
| - // instead of working on strings.
|
| ClassMirror ownerClass;
|
| DeclarationMirror context = owner;
|
| - while (context != null) {
|
| + 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) {
|
| + if (type == null){
|
| return JsMirrorSystem._dynamicType;
|
| } else if (ownerClass == null) {
|
| representation = runtimeTypeToString(type);
|
| @@ -2180,13 +2134,7 @@ List extractMetadata(victim) {
|
| preserveMetadata();
|
| var 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();
|
| - }
|
| + if (JS('String', 'typeof #', victim) != 'function') return const [];
|
| String source = JS('String', 'Function.prototype.toString.call(#)', victim);
|
| int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}'));
|
| if (index == -1) return const [];
|
| @@ -2266,33 +2214,6 @@ bool isReflectiveDataInPrototype(String key) {
|
| return firstChar == '*' || firstChar == '+';
|
| }
|
|
|
| -class NoSuchStaticMethodError extends Error implements NoSuchMethodError {
|
| - static const int MISSING_CONSTRUCTOR = 0;
|
| - 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;
|
| -
|
| - String toString() {
|
| - switch(_kind) {
|
| - case MISSING_CONSTRUCTOR:
|
| - return
|
| - "NoSuchMethodError: No constructor named '${n(_name)}' in class"
|
| - " '${n(_cls.qualifiedName)}'.";
|
| - default:
|
| - return 'NoSuchMethodError';
|
| - }
|
| - }
|
| -}
|
| -
|
| // Copied from package "unmodifiable_collection".
|
| // TODO(14314): Move to dart:collection.
|
| class UnmodifiableMapView<K, V> implements Map<K, V> {
|
| @@ -2332,3 +2253,13 @@ class UnmodifiableMapView<K, V> implements Map<K, V> {
|
|
|
| void clear() => _throw();
|
| }
|
| +
|
| +// TODO(ahe): Remove this class and call noSuchMethod instead.
|
| +class UnimplementedNoSuchMethodError extends Error
|
| + implements NoSuchMethodError {
|
| + final String _message;
|
| +
|
| + UnimplementedNoSuchMethodError(this._message);
|
| +
|
| + String toString() => "Unsupported operation: $_message";
|
| +}
|
|
|