Vincent Bussol created JEXL-456:
-----------------------------------

             Summary: Change in template parser behavior
                 Key: JEXL-456
                 URL: https://issues.apache.org/jira/browse/JEXL-456
             Project: Commons JEXL
          Issue Type: Bug
    Affects Versions: 3.6.2
            Reporter: Vincent Bussol


h3. Jexl 3.5.0

The template parser allows to write:
{code:java}
$$ var foo = 'foo'; $$ var bar = 'bar';
${foo + bar}{code}
Depending on the configuration, the result (evaluation) may be different.
 * strict = true
 * strict = false
 * strict = true/false with a global variable '$$'

{code:java}
@Test
void testIssue350_456_strict() {
    final JexlEngine jexl = new JexlBuilder().strict(true).create();
    final JxltEngine jxlt = jexl.createJxltEngine();
    // creation/parse is OK
    final JxltEngine.Template template = jxlt.createTemplate("$$ var foo = 
'foo'; $$ var bar = 'bar';\n${foo + bar}");
    final StringWriter writer = new StringWriter();
    try {
        template.evaluate(null, writer);
    } catch (JexlException xjexl) {
        // variable '$$' is undefined
        System.out.println(xjexl.getMessage());
    }
}

@Test
void testIssue350_456_notStrict() {
    final JexlEngine jexl = new JexlBuilder().strict(false).create();
    final JxltEngine jxlt = jexl.createJxltEngine();
    // creation/parse is OK
    final JxltEngine.Template template = jxlt.createTemplate("$$ var foo = 
'foo'; $$ var bar = 'bar';\n${foo + bar}");
    final StringWriter writer = new StringWriter();
    template.evaluate(null, writer);
    Assertions.assertEquals("foobar", writer.toString());
}

@Test
void testIssue350_456_strictWithVariable() {
    final JexlEngine jexl = new JexlBuilder().strict(true).create();
    final JxltEngine jxlt = jexl.createJxltEngine();
    // creation/parse is OK
    final JxltEngine.Template template = jxlt.createTemplate("$$ var foo = 
'foo'; $$ var bar = 'bar';\n${foo + bar}");
    // add a '$$' global context variable
    JexlContext ctxt = new MapContext();
    ctxt.set("$$", "");
    final StringWriter writer = new StringWriter();
    template.evaluate(ctxt, writer);
    Assertions.assertEquals("foobar", writer.toString());
} {code}
h3. Jexl 3.6.x

The previous syntax is no longer allowed by the template parser.
{code:java}
@Test
void testIssue36x_456() {
    final JexlEngine jexl = new JexlBuilder().create();
    final JxltEngine jxlt = jexl.createJxltEngine();
    // creation/parse is KO
    try {
        jxlt.createTemplate("$$ var foo = 'foo'; $$ var bar = 'bar';\n${foo + 
bar}");
    } catch (JexlException xjexl) {
        // parsing error in 'var'
        System.out.println(xjexl.getMessage());
    }
} {code}
This can be considered the expected behavior.

However, when a parser error occurs, it would seem that a state persists. Some 
scripts or templates are strangely encountering errors.

For example:
{code:java}
@Test
void testIssue36x_456_var() {
    final JexlEngine jexl = new JexlBuilder().create();
    final JxltEngine jxlt = jexl.createJxltEngine();
    // OK
    jexl.createScript("var foo = 0;\nfoo = 42;");
    try {
        jxlt.createTemplate("$$ var foo = 'foo'; if (true) { var foo = 'bar'; 
var err =&; }");
    } catch (JexlException xjexl) {
        // parsing error in '&'
        System.out.println(xjexl.getMessage());
    }
    // java.lang.NullPointerException: Cannot invoke 
"org.apache.commons.jexl3.internal.Scope.getCaptureDeclaration(int)" because 
"blockScope" is null
    jexl.createScript("var foo = 0;\nfoo = 42;");
    // same error with the template creation below
    //jxlt.createTemplate("$$ var foo = 'foo'; foo = 'bar';");
}

@Test
void testIssue36x_456_let() {
    final JexlEngine jexl = new Engine32(new JexlBuilder().strict(true));
    // OK
    jexl.createScript("let foo = 0;\nfoo = 42;");
    final JxltEngine jxlt = jexl.createJxltEngine();
    try {
        jxlt.createTemplate("$$ var err =&;");
    } catch (JexlException xjexl) {
        // parsing error in '&'
        System.out.println(xjexl.getMessage());
    }
    // parsing error in 'foo: variable is already declared'
    jexl.createScript("let foo = 0;\nfoo = 42;");
    // same error with the template creation below
    //jxlt.createTemplate("$$ let foo = 0;\nfoo = 42;");
} {code}
Note that when a script error occurs, the next call is correct again. This is 
not the case for a template.
{code:java}
@Test
void testIssue36x_456_let_script() {
    final JexlEngine jexl = new Engine32(new JexlBuilder().strict(true));
    // OK
    jexl.createScript("let foo = 0;\nfoo = 42;");
    final JxltEngine jxlt = jexl.createJxltEngine();
    try {
        jxlt.createTemplate("$$ var err =&;");
    } catch (JexlException xjexl) {
        // parsing error in '&'
        System.out.println(xjexl.getMessage());
    }
    try {
        jexl.createScript("let foo = 0; foo = 42;");
    } catch (JexlException xjexl) {
        // ignore - parsing error in 'foo: variable is already declared'
        System.out.println(xjexl.getMessage());
    }
    // the next call is OK
    jexl.createScript("let foo = 0; foo = 42;");
}

@Test
void testIssue36x_456_let_template() {
    final JexlEngine jexl = new Engine32(new JexlBuilder().strict(true));
    // OK
    jexl.createScript("let foo = 0;\nfoo = 42;");
    final JxltEngine jxlt = jexl.createJxltEngine();
    try {
        jxlt.createTemplate("$$ var err =&;");
    } catch (JexlException xjexl) {
        // parsing error in '&'
        System.out.println(xjexl.getMessage());
    }
    try {
        jxlt.createTemplate("$$ let foo = 0;\nfoo = 42;");
    } catch (JexlException xjexl) {
        // ignore - parsing error in 'foo: variable is already declared'
        System.out.println(xjexl.getMessage());
    }
    // the next call is still KO
    jxlt.createTemplate("$$ let foo = 0;\nfoo = 42;");
} {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to