Invoked when a non-existent method or property is accessed.
Classes can override noSuchMethod
to provide custom behavior.
If a value is returned, it becomes the result of the original invocation.
The default behavior is to throw a NoSuchMethodError
.
Source
noSuchMethod(Invocation invocation) {
throwError() {
throw new NoSuchMethodError(this, invocation.memberName,
invocation.positionalArguments, invocation.namedArguments);
}
String name = mirrors.MirrorSystem.getName(invocation.memberName);
if (invocation.isGetter) {
if (CHECK_JS_INVOCATIONS) {
var matches = _allowedGetters[invocation.memberName];
if (matches == null &&
!_allowedMethods.containsKey(invocation.memberName)) {
throwError();
}
var ret = this[name];
if (matches != null && matches._checkReturnType(ret)) return ret;
if (ret is Function ||
(ret is JsFunction /* shouldn't be needed in the future*/) &&
_allowedMethods.containsKey(
invocation.memberName)) return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
throwError();
} else {
// TODO(jacobr): should we throw if the JavaScript object doesn't have the property?
return maybeWrapTypedInterop(this._operator_getter(name));
}
} else if (invocation.isSetter) {
if (CHECK_JS_INVOCATIONS) {
var matches = _allowedSetters[invocation.memberName];
if (matches == null ||
!matches.checkInvocation(invocation)) throwError();
}
assert(name.endsWith("="));
name = name.substring(0, name.length - 1);
return maybeWrapTypedInterop(_operator_setter(
name, invocation.positionalArguments.first));
} else {
// TODO(jacobr): also allow calling getters that look like functions.
var matches;
if (CHECK_JS_INVOCATIONS) {
matches = _allowedMethods[invocation.memberName];
if (matches == null ||
!matches.checkInvocation(invocation)) throwError();
}
var ret = maybeWrapTypedInterop(this._callMethod(name, _buildArgs(invocation)));
if (CHECK_JS_INVOCATIONS) {
if (!matches._checkReturnType(ret)) throwError();
}
return ret;
}
}