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)