Is nested closure permission different between methods and properties?
When you close, the Strategy permission is set to DELEGATE_ONLY
or DELEGATE_FIRST
, the permission is different from nested closures between delegate methods and properties. For example, in the following, x
allows f
delegating (which is what I expect) but keySet()
allows g
delegating.
def g = {->
def f = {
{-> [x, keySet()]}()
}
f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ['x', 'g']]
Whereas without nested closure
def g = {->
def f = {
[x, keySet()]
}
f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ['x', 'f']]
Is this behavior expected and documented somewhere? This is mistake?
source to share
I believe this is a mistake. If you change the map for Expando
, it will be different:
f = {
g = {
{ -> keySet() }()
}
g.delegate = new Expando(a: 1000, b: 900, c: 800, keySet: { 'g keyset' })
g.resolveStrategy = Closure.DELEGATE_ONLY
g()
}
f.delegate = new Expando(a: 90, x: 9, y: 1, keySet: { 'f keyset' })
assert f() == 'g keyset'
f = {
g = {
{ -> keySet() }()
}
g.delegate = [a: 1000, b: 900, c: 800]
g.resolveStrategy = Closure.DELEGATE_ONLY
g()
}
f.delegate = [a: 90, x: 9, y: 1]
assert f().toList() == ['a', 'b', 'c'] // fails :-(
JIRA filling possible ?
source to share
I found a workaround if you never want to miss the owner (i.e. DELEGATE_ONLY
): you can set both the delegate and the owner to the same value:
def g = {->
def f = {
{-> [x, keySet()]}()
}
def d = [x: 1, f: 0]
f = f.rehydrate(d, d, f.thisObject)
f()
}
g.delegate = [x: 0, g: 0]
g()
Result: [1, ["x", "f"]]
Note that f.owner = d
doesn't work: as long as there is no error, it appears to be a non-op. You must use rehydrate
.
source to share