Ivan Kuznetsov created GROOVY-9283:
--------------------------------------

             Summary: Nested closures run on wrong delegate
                 Key: GROOVY-9283
                 URL: https://issues.apache.org/jira/browse/GROOVY-9283
             Project: Groovy
          Issue Type: Bug
          Components: Static compilation
    Affects Versions: 3.0.0-beta-3, 2.5.7
         Environment: CentOS Linux release 7.7.1908 (Core), openjdk 12.0.2 
2019-07-16

            Reporter: Ivan Kuznetsov


We use Groovy to write DSL scripts for our project, and the only version we can 
use now is 2.5.6 because of bug with {{\@CompileStatic}} wich is reproducible 
with the following code:
{code:java}
package test;

import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import groovy.lang.GroovyClassLoader;
import groovy.transform.CompileStatic;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
import org.codehaus.groovy.runtime.InvokerHelper;

public class Main {
    private static final String script = "" +
            "import test.Main\n" +
            "\n" +
            "new Main().enter {\n" +
            "    nest {\n" +
            "        nest {\n" +
            "            nest {\n" +
            "                println(\"REACHED\")\n" +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}\n";

    public static void main(String[] args) {
        CompilerConfiguration config = new CompilerConfiguration();
        config.addCompilationCustomizers(new 
ASTTransformationCustomizer(CompileStatic.class));
        GroovyClassLoader loader = new 
GroovyClassLoader(Main.class.getClassLoader(), config);
        Class<?> cls = loader.parseClass(script, "file");
        InvokerHelper.runScript(cls, new String[0]);
    }

    public void enter(@DelegatesTo(Root.class) Closure<?> closure) {
        Root scope = new Root();
        closure.setDelegate(scope);
        closure.run();
    }

    public static class Outer extends Main {
        private final Main parent;

        Outer() {
            this.parent = null;
        }

        Outer(Outer parent) {
            this.parent = parent;
        }

        public void nest(@DelegatesTo(Inner.class) Closure<?> closure) {
            closure.setDelegate(new Inner(this));
            closure.run();
            System.out.println(this + ": " + parent);
        }
    }

    public static class Inner extends Outer {

        public Inner(Outer parent) {
            super(parent);
        }
    }

    public static class Root extends Outer {
        Root() {
        }
    }
}
{code}

till version 2.5.6 it prints:
{noformat}
REACHED
test.Main$Inner@7582ff54: test.Main$Inner@67545b57
test.Main$Inner@67545b57: test.Main$Root@6c2c1385
test.Main$Root@6c2c1385: null
{noformat}
but starting with 2.5.7 it prints:
{noformat}
REACHED
test.Main$Root@2f67b837: null
test.Main$Root@2f67b837: null
test.Main$Root@2f67b837: null
{noformat}

The workaround is to turn off static compilation, but it degrades performance 
because some handles are defined using this DSL and they are called very often.

Thanks in advance!



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to