interpretedCallMethod method
SCD145 — the clause a member error should carry when its receiver is a NATIVE object that no bridge claims.
Environment.toBridgedClass throws
Cannot bridge native object: No registered bridged class found for native type … and toBridgedInstance above catches it, revoke()s it and
returns (null, false). That catch is correct and load-bearing: its
callers use the false as a CONTROL-FLOW signal and fall through to other
registries, because an interpreter-internal value legitimately has no
bridge. The cost is that the real cause is gone by the time the
fallthrough chain gives up, and what the script author sees is
Undefined property or method 'moveNext' on _TallyIterator
which points at the member. The reader goes looking for a missing method on a bridge that does not exist.
This recovers the cause at the point of failure. It changes only the
MESSAGE — not the exception type, not memberName, not receiver, and not
the control flow. environment.dart's own note records why widening
resolution instead broke 43 enum-dispatch tests: callers use the throw as
a signal. A message change on a path that is already failing cannot
regress a passing one.
Returns '' for anything that is not in that situation, and the two
exclusions are the interesting part:
- Interpreter-internal values. Tested against the abstractions the
interpreter owns —
RuntimeValue,RuntimeType,Callable,InterpretedRecord— rather than a list of concrete types, because a list is what rots when a new value shape appears. A script-declared class has no bridge and is not supposed to, so saying so would be noise on every script typo. - Types a bridge DOES claim. There the member really is the problem
and the new wording would be a lie.
Dart's callable-object rule for an interpreted instance:
a(3)meansa.call(3)when the class, a superclass or a mixin declares an instance method namedcall. Returns that method bound tovalue, or null whenvalueis not such an instance.
Both call paths ask this before deciding a value is not callable. Until SCE176 neither did: a call through a variable fell through to returning the instance itself, and a call through an expression threw.
Implementation
Callable? interpretedCallMethod(Object? value) {
if (value is! InterpretedInstance) return null;
return value.klass.findInstanceMethod('call')?.bind(value);
}