Scott Murphy Heiberg created GROOVY-12665:
---------------------------------------------
Summary: rehydrate() on a curried, writable, composed or
trampolined closure throws ClassCastException or ignores the new owner and
delegate
Key: GROOVY-12665
URL: https://issues.apache.org/jira/browse/GROOVY-12665
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 O { def foo() { 'o' } }
class D { def foo() { 'd' } }
def c = { x, y -> foo() + x + y }
assert c.rehydrate(new D(), new O(), new O()).curry(1)(2) == 'o12' // passes
assert c.curry(1).rehydrate(new D(), new O(), new O())(2) == 'o12' // fails
{code}
*Actual:* {{java.lang.ClassCastException: class O cannot be cast to class
groovy.lang.Closure}}, thrown at {{CurriedClosure.getOwner}} from
{{CurriedClosure.call}} (on 4.0.33 a MissingMethodException for O.doCall()).
* {{c.curry(1).dehydrate()}} throws NullPointerException when called.
* {{c.asWritable().rehydrate(...)}} throws the same ClassCastException.
* For {{(c >> g).rehydrate(...)}} and {{c.trampoline().rehydrate(...)}} the new
owner and delegate are ignored: {{foo()}} still resolves against the original
owner.
* {{dehydrate()}} on a composed or trampolined closure still holds the original
owner, so the result cannot be serialized.
*Expected:* rehydrating or dehydrating a wrapper closure behaves like
rehydrating or dehydrating the closure it wraps and wrapping the copy.
Cause: {{Closure.rehydrate}} and {{Closure.dehydrate}} replace only the
wrapper's own owner, delegate and thisObject fields. {{CurriedClosure}} and
{{Closure.WritableClosure}} keep the wrapped closure in owner, so it is
overwritten. {{ComposedClosure}} and {{TrampolineClosure}} call through
separate fields, so the wrapped closures are never rehydrated or dehydrated.
Verified on 4.0.33, 5.0.8, 6.0.0 and master.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)