| Index: sdk/lib/_internal/lib/js_mirrors.dart
|
| diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
|
| index 2c59de0bddf03511fc6fb965adaa37759aa59cba..ceb177f872fe6584ba45af99180f097958e13d18 100644
|
| --- a/sdk/lib/_internal/lib/js_mirrors.dart
|
| +++ b/sdk/lib/_internal/lib/js_mirrors.dart
|
| @@ -341,13 +341,7 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| // TODO(ahe): What receiver to use?
|
| throw new NoSuchMethodError(this, 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);
|
| - String getter = JS("", "#['\$getter']", methodMirror._jsFunction);
|
| - if (getter == null) throw new UnimplementedError();
|
| - return reflect(JS("", "#()", getter));
|
| + return reflect(mirror._getField(this));
|
| }
|
|
|
| InstanceMirror invoke(Symbol memberName,
|
| @@ -357,20 +351,15 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| 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) {
|
| + if (mirror == null) {
|
| // TODO(ahe): What receiver to use?
|
| throw new NoSuchMethodError(
|
| this, memberName, positionalArguments, namedArguments);
|
| }
|
| - if (mirror is JsMethodMirror && !mirror.isGetter) {
|
| - return reflect(mirror._invoke(positionalArguments, namedArguments));
|
| + if (mirror is JsMethodMirror && !mirror.canInvokeReflectively()) {
|
| + throwInvalidReflectionError(n(memberName));
|
| }
|
| - return getField(memberName)
|
| - .invoke(#call, positionalArguments, namedArguments);
|
| + return reflect(mirror._invoke(positionalArguments, namedArguments));
|
| }
|
|
|
| _loadField(String name) {
|
| @@ -398,7 +387,7 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
| var jsFunction = JS('', '#[#]', _globalObject, name);
|
| String unmangledName = mangledGlobalNames[name];
|
| if (unmangledName == null ||
|
| - JS('bool', "!!#['\$getterStub']", jsFunction)) {
|
| + JS('bool', "!!#['getterStub']", jsFunction)) {
|
| // If there is no unmangledName, [jsFunction] is either a synthetic
|
| // implementation detail, or something that is excluded
|
| // by @MirrorsUsed.
|
| @@ -827,61 +816,61 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| 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.
|
| + 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');
|
| }
|
| - });
|
| - positionalArguments.addAll(defaultArguments.values);
|
| - // TODO(ahe): Handle intercepted methods.
|
| - return reflect(
|
| - JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments));
|
| + 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));
|
| + } else {
|
| + reflectiveName =
|
| + JS('String', '# + ":" + # + ":0"', name, positionalArguments.length);
|
| + }
|
| + // We can safely pass positionalArguments to _invoke as it will wrap it in
|
| + // a JSArray if needed.
|
| + return _invoke(memberName, JSInvocationMirror.METHOD, reflectiveName,
|
| + positionalArguments);
|
| }
|
|
|
| /// Grabs hold of the class-specific invocation cache for the reflectee.
|
| @@ -899,94 +888,55 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| 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:0";
|
| - }
|
| - 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) {
|
| -
|
| + /// 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,
|
| + String reflectiveName,
|
| + List arguments) {
|
| var cache = _classInvocationCache;
|
| var cacheEntry = JsCache.fetch(cache, reflectiveName);
|
| var result;
|
| + Invocation invocation;
|
| if (cacheEntry == null) {
|
| disableTreeShaking();
|
| String mangledName = reflectiveNames[reflectiveName];
|
| List<String> argumentNames = const [];
|
| + if (type == JSInvocationMirror.METHOD) {
|
| + // Note: [argumentNames] are not what the user actually provided, it is
|
| + // always all the named parameters.
|
| + argumentNames = reflectiveName.split(':').skip(3).toList();
|
| + }
|
|
|
| // 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);
|
| + invocation = createUnmangledInvocationMirror(
|
| + name, mangledName, type, arguments, argumentNames);
|
|
|
| cacheEntry =
|
| JSInvocationMirror.getCachedInvocation(invocation, reflectee);
|
| JsCache.update(cache, reflectiveName, cacheEntry);
|
| }
|
| - return cacheEntry;
|
| - }
|
| -
|
| - /// 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) {
|
| - // 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 (invocation == null) {
|
| + String mangledName = reflectiveNames[reflectiveName];
|
| + // TODO(ahe): Get the argument names.
|
| + List<String> argumentNames = [];
|
| + invocation = createUnmangledInvocationMirror(
|
| + name, mangledName, type, arguments, argumentNames);
|
| }
|
| -
|
| - if (type == JSInvocationMirror.SETTER) {
|
| - // For setters we report the setter name "field=".
|
| - name = s("${n(name)}=");
|
| - }
|
| -
|
| - 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));
|
| + return reflect(cacheEntry.invokeOn(reflectee, arguments));
|
| }
|
| }
|
|
|
| InstanceMirror setField(Symbol fieldName, Object arg) {
|
| - _invoke(fieldName, JSInvocationMirror.SETTER, [arg], const {});
|
| + String reflectiveName = '${n(fieldName)}=';
|
| + _invoke(
|
| + s(reflectiveName), JSInvocationMirror.SETTER, reflectiveName, [arg]);
|
| return reflect(arg);
|
| }
|
|
|
| @@ -1014,15 +964,6 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| /// 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) {
|
| // BUG(16400): This should be a labelled block, but that makes
|
| // dart2js crash when merging locals information in the type
|
| @@ -1055,9 +996,8 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
|
| 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 result = _invoke(fieldName, JSInvocationMirror.GETTER, name, const []);
|
| var cacheEntry = JsCache.fetch(_classInvocationCache, name);
|
| if (cacheEntry.isNoSuchMethod) {
|
| return result;
|
| @@ -1783,13 +1723,6 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| throw new NoSuchMethodError(this, setterSymbol(fieldName), [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) {
|
| @@ -1806,21 +1739,6 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| 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).
|
| - String getter = JS("", "#['\$getter']", method._jsFunction);
|
| - if (getter == null) throw new UnimplementedError();
|
| - return reflect(JS("", "#()", getter));
|
| - }
|
| // TODO(ahe): What receiver to use?
|
| throw new NoSuchMethodError(this, fieldName, null, null);
|
| }
|
| @@ -1921,11 +1839,6 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
|
| 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) {
|
| // TODO(ahe): What receiver to use?
|
| throw new NoSuchMethodError(
|
|
|