Scott Murphy Heiberg created GROOVY-12673:
---------------------------------------------

             Summary: Closure wrappers (trampoline, memoize, curry, compose, 
asWritable) report the wrong delegate or thisObject and ignore delegate and 
resolveStrategy changes
                 Key: GROOVY-12673
                 URL: https://issues.apache.org/jira/browse/GROOVY-12673
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 5.0.8, 4.0.33, 6.0.0, 7.0.0-alpha-1
            Reporter: Scott Murphy Heiberg


{code:groovy}
class D { def m() { 'delegate' } }
class O {
    def m() { 'owner' }
    def run() {
        def c = { x -> m() }
        assert c.curry(1).thisObject.is(this)        // fails: null (also for c 
>> {...}, and c.asWritable().getThisObject())
        def t = c.trampoline()
        assert t.thisObject.is(this)                 // fails: the delegate of c
        t.resolveStrategy = Closure.DELEGATE_FIRST
        t.delegate = new D()
        assert t(1) == 'delegate'                    // fails: 'owner'
        def m = { x -> m() }.memoize()
        m.resolveStrategy = Closure.DELEGATE_FIRST
        m.delegate = new D()
        assert m(1) == 'delegate'                    // fails: 'owner'
    }
}
new O().run()
{code}
*Actual:* curried and composed closures report a null thisObject. A writable 
closure's getThisObject() returns null, so the property read under 
@CompileStatic gives null too. A trampolined closure reports the wrapped 
closure's delegate as its thisObject and its owner as its delegate. A memoized 
closure reports the owner as its delegate and null as its thisObject. Setting 
delegate or resolveStrategy on a trampolined or memoized closure has no effect 
on the call. {{c.asWritable().trampoline()}} also reports one Object[] 
parameter instead of the parameters of c.

*Expected:* a wrapper reports the delegate, resolve strategy and thisObject of 
the closure it wraps, and setting delegate or resolveStrategy on it applies to 
that closure, as ComposedClosure and CurriedClosure already do for delegate and 
resolveStrategy.

Cause: TrampolineClosure passes original.getDelegate() as thisObject, and 
neither TrampolineClosure nor Memoize.MemoizeFunction forwards the delegate and 
resolve strategy. CurriedClosure, ComposedClosure and WritableClosure do not 
forward getThisObject. TrampolineClosure reads the wrapped closure's parameter 
fields instead of its getters.

Verified on 4.0.33, 5.0.8, 6.0.0 and master.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to