codeconsole opened a new pull request, #3186:
URL: https://github.com/apache/groovy/pull/3186

   `rehydrate` and `dehydrate` on a closure wrapper did not reach the closure 
being wrapped:
   
   ```groovy
   class O { def foo() { 'o' } }
   class D { def foo() { 'd' } }
   def c = { x, y -> foo() + x + y }
   c.curry(1).rehydrate(new D(), new O(), new O())(2)
   // ClassCastException: class O cannot be cast to class groovy.lang.Closure
   ```
   
   `Closure.rehydrate` and `Closure.dehydrate` copy the closure and replace its 
`owner`, `delegate` and `thisObject` fields.
   
   - `CurriedClosure` and `Closure.WritableClosure` keep the wrapped closure in 
`owner`. Rehydrating replaced it with the new owner, and the next call failed 
with a ClassCastException. Dehydrating set it to null, and the next call failed 
with a NullPointerException.
   - `ComposedClosure` and `TrampolineClosure` call through their own fields. 
Rehydrating them changed nothing that is called, so methods still resolved 
against the original owner. Dehydrating them left that owner reachable, so the 
result could not be serialized, which is the reason `dehydrate` exists.
   
   Seen in 4.0.33, 5.0.8 and 6.0.0 too.
   
   Each of the four wrappers now overrides `dehydrate()` and `rehydrate(Object, 
Object, Object)`. The override applies the operation to the wrapped closure 
(both closures for a composition) and wraps the copy again, so the result 
behaves like rehydrating the original closure and then currying, composing, 
trampolining or making it writable. There is one commit per wrapper. Memoized 
closures are left out: their cache needs a separate decision.
   
   ## Tests
   
   These fail without the change:
   - `ClosureCurryTest.testRehydrateCurriedClosure` and 
`testDehydrateCurriedClosure`
   - `ClosureTest.testDehydrateAndRehydrateWritableClosure`
   - `ClosureComposeTest.testRehydrateComposedClosure` and 
`testDehydrateComposedClosure`
   - `TrampolineTest.testRehydrateTrampolinedClosure` and 
`testDehydrateTrampolinedClosure`
   
   They cover `curry`, `rcurry`, `ncurry` and nested curry, `DELEGATE_FIRST`, 
`>>` and `<<`, and serialize, deserialize and rehydrate round trips. The 
`groovy.lang.*Closure*`, `groovy.*Closure*`, 
`org.codehaus.groovy.runtime.*Closure*`, 
`org.codehaus.groovy.runtime.trampoline.*` and 
`org.codehaus.groovy.runtime.memoize.*` tests pass, as do `ClosuresSTCTest`, 
`DelegatesToSTCTest`, `ClosuresStaticCompileTest` and 
`PackedClosuresTransformTest`. The Checkstyle and CodeNarc gates pass.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to