blob: d2c11c98ee91b4241d6fe87c6ecda151fd7dd349 [file] [log] [blame]
// Copyright (c) 2017, 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.
/// An object that uses [noSuchMethod] to dynamically handle invocations
/// (property getters, property setters, and method invocations).
abstract class ProxyObject {}
/// A function reference that, when invoked, will forward the invocation back
/// to a [ProxyObject].
///
/// This is used when a caller accesses a method on a [ProxyObject] via the
/// method's getter. In these cases, the caller will receive a [MethodProxy]
/// that allows delayed invocation of the method.
class MethodProxy {
/// The object on which the method was retrieved.
///
/// This will be the target object when this method proxy is invoked.
final ProxyObject _proxyObject;
/// The name of the method in question.
final Symbol _methodName;
/// Creates a new [MethodProxy] that, when invoked, will invoke the method
/// identified by [methodName] on the specified target [object].
MethodProxy(ProxyObject object, Symbol methodName)
: _proxyObject = object,
_methodName = methodName;
@override
dynamic noSuchMethod(Invocation invocation) {
if (invocation.isMethod && invocation.memberName == #call) {
// The method is being invoked. Capture the arguments, and invoke the
// method on the proxy object. We have to synthesize an invocation, since
// our current `invocation` object represents the invocation of `call()`.
return _proxyObject.noSuchMethod(new _MethodInvocationProxy(
_methodName,
invocation.positionalArguments,
invocation.namedArguments,
));
}
return super.noSuchMethod(invocation);
}
}
// TODO(tvolkert): remove (https://github.com/dart-lang/sdk/issues/28706)
class _MethodInvocationProxy extends Invocation {
_MethodInvocationProxy(
this.memberName,
this.positionalArguments,
this.namedArguments,
);
@override
final Symbol memberName;
@override
final List<dynamic> positionalArguments;
@override
final Map<Symbol, dynamic> namedArguments;
@override
final bool isMethod = true;
@override
final bool isGetter = false;
@override
final bool isSetter = false;
}