Scott Murphy Heiberg created GROOVY-12679:
---------------------------------------------
Summary: Closures from
AsyncClosureUtils.wrapAsync/wrapAsyncGenerator ignore the delegate and resolve
strategy and misreport their parameters
Key: GROOVY-12679
URL: https://issues.apache.org/jira/browse/GROOVY-12679
Project: Groovy
Issue Type: Bug
Affects Versions: 6.0.0, 7.0.0-alpha-1
Reporter: Scott Murphy Heiberg
{code:groovy}
import org.apache.groovy.runtime.async.AsyncClosureUtils
class Ctx { String greet() { 'hi' } }
Closure wrapped = AsyncClosureUtils.wrapAsync { -> greet() }
wrapped.delegate = new Ctx()
wrapped.resolveStrategy = Closure.DELEGATE_FIRST
assert await(wrapped()) == 'hi'
assert await(new Ctx().with(AsyncClosureUtils.wrapAsync { greet() })) == 'hi'
def w = AsyncClosureUtils.wrapAsync { String k, Integer v -> k * v }
assert w.maximumNumberOfParameters == 2
assert [a: 1, b: 2].collect(w).collect { await(it) } == ['a', 'bb']
{code}
*Actual:* MissingMethodException: No signature of method: greet for class:
Script1. After setting a delegate on the wrapper, getDelegate() still returns
the script and getResolveStrategy() returns OWNER_FIRST. If the wrapped closure
is configured instead, the wrapper reports its own owner and OWNER_FIRST. The
wrapper reports one Object[] parameter, so Map.collect passes the entry to a
two-parameter closure and fails with MissingMethodException: doCall ...
(Entry). wrapAsyncGenerator behaves the same.
*Expected:* the same behaviour as calling the wrapped closure directly: names
resolve against the delegate, with(), dehydrate() and rehydrate() work, and the
wrapped closure's parameters are reported.
Cause: the wrappers are anonymous Closure subclasses that copy only the owner
and this object of the wrapped closure. They keep their own delegate and
resolve strategy, which the wrapped closure never sees, and report the
parameters of their own doCall(Object...).
Verified on 6.0.0 and master (the API is new in 6.0.0).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)