Scott Murphy Heiberg created GROOVY-12664:
---------------------------------------------

             Summary: Implicit-this call to an Object extension method inside a 
closure runs twice when delegate and owner cannot take it
                 Key: GROOVY-12664
                 URL: https://issues.apache.org/jira/browse/GROOVY-12664
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 6.0.0, 7.0.0-alpha-1
            Reporter: Scott Murphy Heiberg


{code:groovy}
int count = 0
def c = { -> with { ++count } }
c.resolveStrategy = Closure.DELEGATE_ONLY
c.delegate = null
def result = c()
println "result=$result count=$count"
{code}
*Actual* (6.0.0 and master): {{result=2 count=2}}. The {{with}} block runs 
twice. Calling the metaclass directly, as 
{{c.metaClass.invokeMethod(this.getClass(), c, 'sprintf', ['%d', 42] as 
Object[], false, true)}}, throws MissingMethodException.

*Expected* (as in 4.0.33 and 5.0.8): {{result=1 count=1}}, and the direct 
metaclass call returns "42".

The same happens with a delegate that is the closure itself, after dehydrate() 
with DELEGATE_ONLY, after rehydrate(null, null, null) with OWNER_ONLY, and with 
@TypeChecked.

Cause: GROOVY-11858 made {{ClosureMetaClass.invokeMethod}} defer a non-closure 
method so that delegate and owner are tried first. When neither can take the 
call, the deferred method is invoked but its result is not returned, and 
MissingMethodException is thrown. The indy fallback then retries through 
GroovyObject.invokeMethod and calls the method again.

Verified: 6.0.0 and master affected; 4.0.33 and 5.0.8 not affected.



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

Reply via email to