You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2022/05/16 16:58:40 UTC
[commons-jexl] branch master updated: JEXL-369: move const/defined logic to lexical scope; - restore explicit lexical shade through features; - detect non-initialized const variables
This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/master by this push:
new 4ddf1831 JEXL-369: move const/defined logic to lexical scope; - restore explicit lexical shade through features; - detect non-initialized const variables
4ddf1831 is described below
commit 4ddf18313cadee541132d19beac62fcaa02f7321
Author: henrib <he...@apache.org>
AuthorDate: Mon May 16 18:58:33 2022 +0200
JEXL-369: move const/defined logic to lexical scope;
- restore explicit lexical shade through features;
- detect non-initialized const variables
---
.../commons/jexl3/internal/LexicalFrame.java | 2 +-
.../commons/jexl3/internal/LexicalScope.java | 143 ++++++++++++++++-----
.../org/apache/commons/jexl3/internal/Scope.java | 25 ----
.../apache/commons/jexl3/parser/ASTIdentifier.java | 10 ++
.../commons/jexl3/parser/JexlLexicalNode.java | 40 +++++-
.../apache/commons/jexl3/parser/JexlParser.java | 55 +++++---
.../org/apache/commons/jexl3/parser/Parser.jjt | 13 +-
.../java/org/apache/commons/jexl3/LambdaTest.java | 25 ++++
.../java/org/apache/commons/jexl3/LexicalTest.java | 20 ++-
9 files changed, 242 insertions(+), 91 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/internal/LexicalFrame.java b/src/main/java/org/apache/commons/jexl3/internal/LexicalFrame.java
index 6bf8cbdd..59fd6315 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/LexicalFrame.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/LexicalFrame.java
@@ -54,7 +54,7 @@ public class LexicalFrame extends LexicalScope {
* @param src the frame to copy
*/
public LexicalFrame(final LexicalFrame src) {
- super(src.symbols, src.moreSymbols);
+ super(src);
frame = src.frame;
previous = src.previous;
stack = src.stack != null ? new ArrayDeque<>(src.stack) : null;
diff --git a/src/main/java/org/apache/commons/jexl3/internal/LexicalScope.java b/src/main/java/org/apache/commons/jexl3/internal/LexicalScope.java
index 4059e55e..5551551a 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/LexicalScope.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/LexicalScope.java
@@ -20,7 +20,10 @@ import java.util.BitSet;
/**
* The set of symbols declared in a lexical scope.
- * <p>The symbol identifiers are determined by the functional scope.
+ * <p>The symbol identifiers are determined by the functional scope.</p>
+ * <p>We use 3 bits per symbol; bit 0 sets the actual symbol as lexical (let),
+ * bit 1 as a const, bit 2 as a defined (valued) const.
+ * There are actually only 4 used states: 0, 1, 3, 7</p>
*/
public class LexicalScope {
/**
@@ -28,7 +31,16 @@ public class LexicalScope {
*/
protected static final int LONGBITS = 64;
/**
- * The mask of symbols in the frame.
+ * Bits per symbol.
+ * Declared, const, defined.
+ */
+ protected static final int BITS_PER_SYMBOL = 3;
+ /**
+ * Number of symbols.
+ */
+ protected int count = 0;
+ /**
+ * The mask of symbols in the scope.
*/
protected long symbols = 0L;
/**
@@ -36,6 +48,7 @@ public class LexicalScope {
*/
protected BitSet moreSymbols = null;
+
/**
* Create a scope.
*/
@@ -44,21 +57,20 @@ public class LexicalScope {
/**
* Frame copy ctor base.
- *
- * @param s the symbols mask
- * @param ms the more symbols bitset
*/
- protected LexicalScope(final long s, final BitSet ms) {
- symbols = s;
+ protected LexicalScope(LexicalScope other) {
+ BitSet ms;
+ symbols = other.symbols;
+ ms = other.moreSymbols;
moreSymbols = ms != null ? (BitSet) ms.clone() : null;
}
/**
- * Ensure more symbpls can be stored.
+ * Ensures more symbols can be stored.
*
* @return the set of more symbols
*/
- protected final BitSet moreSymbols() {
+ private BitSet moreSymbols() {
if (moreSymbols == null) {
moreSymbols = new BitSet();
}
@@ -66,32 +78,30 @@ public class LexicalScope {
}
/**
- * Checks whether a symbol has already been declared.
- *
- * @param symbol the symbol
- * @return true if declared, false otherwise
+ * Whether a given bit (not symbol) is set.
+ * @param bit the bit
+ * @return true if set
*/
- public boolean hasSymbol(final int symbol) {
- if (symbol < LONGBITS) {
- return (symbols & (1L << symbol)) != 0L;
+ private boolean isSet(final int bit) {
+ if (bit < LONGBITS) {
+ return (symbols & (1L << bit)) != 0L;
}
- return moreSymbols != null && moreSymbols.get(symbol - LONGBITS);
+ return moreSymbols != null && moreSymbols.get(bit - LONGBITS);
}
/**
- * Adds a symbol in this scope.
- *
- * @param symbol the symbol
- * @return true if registered, false if symbol was already registered
+ * Sets a given bit (not symbol).
+ * @param bit the bit
+ * @return true if it was actually set, false if it was set before
*/
- public boolean addSymbol(final int symbol) {
- if (symbol < LONGBITS) {
- if ((symbols & (1L << symbol)) != 0L) {
+ private boolean set(final int bit) {
+ if (bit < LONGBITS) {
+ if ((symbols & (1L << bit)) != 0L) {
return false;
}
- symbols |= (1L << symbol);
+ symbols |= (1L << bit);
} else {
- final int s = symbol - LONGBITS;
+ final int s = bit - LONGBITS;
final BitSet ms = moreSymbols();
if (ms.get(s)) {
return false;
@@ -101,6 +111,77 @@ public class LexicalScope {
return true;
}
+ /**
+ * Checks whether a symbol has already been declared.
+ *
+ * @param symbol the symbol
+ * @return true if declared, false otherwise
+ */
+ public boolean hasSymbol(final int symbol) {
+ final int bit = symbol << BITS_PER_SYMBOL;
+ return isSet(bit);
+ }
+
+ /**
+ * Checks whether a symbol is declared as a constant.
+ *
+ * @param symbol the symbol
+ * @return true if declared as constant, false otherwise
+ */
+ public boolean isConstant(final int symbol) {
+ final int bit = (symbol << BITS_PER_SYMBOL) | 1;
+ return isSet(bit);
+ }
+
+ /**
+ * Checks whether a const symbol has been defined, ie has a value.
+ *
+ * @param symbol the symbol
+ * @return true if defined, false otherwise
+ */
+ public boolean isDefined(final int symbol) {
+ final int bit = (symbol << BITS_PER_SYMBOL) | 2;
+ return isSet(bit);
+
+ }
+
+ /**
+ * Adds a symbol in this scope.
+ *
+ * @param symbol the symbol
+ * @return true if registered, false if symbol was already registered
+ */
+ public boolean addSymbol(final int symbol) {
+ final int bit = (symbol << BITS_PER_SYMBOL) ;
+ if (set(bit)) {
+ count += 1;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds a constant in this scope.
+ *
+ * @param symbol the symbol
+ * @return true if registered, false if symbol was already registered
+ */
+ public boolean addConstant(final int symbol) {
+ final int bit = (symbol << BITS_PER_SYMBOL) | 1;
+ return set(bit);
+ }
+
+ /**
+ * Defines a constant in this scope.
+ *
+ * @param symbol the symbol
+ * @return true if registered, false if symbol was already registered
+ */
+ public boolean defineSymbol(final int symbol) {
+ final int bit = (symbol << BITS_PER_SYMBOL) | 2;
+ return set(bit);
+ }
+
/**
* Clear all symbols.
*
@@ -112,14 +193,16 @@ public class LexicalScope {
long clean = symbols;
while (clean != 0L) {
final int s = Long.numberOfTrailingZeros(clean);
- clean &= ~(1L << s);
- cleanSymbol.accept(s);
+ // call clean for symbol definition (7 as a mask for 3 bits,1+2+4)
+ clean &= ~(7L << s);
+ cleanSymbol.accept(s >> BITS_PER_SYMBOL);
}
}
symbols = 0L;
if (moreSymbols != null) {
if (cleanSymbol != null) {
- for (int s = moreSymbols.nextSetBit(0); s != -1; s = moreSymbols.nextSetBit(s + 1)) {
+ // step over const and definition (3 bits per symbol)
+ for (int s = moreSymbols.nextSetBit(0); s != -1; s = moreSymbols.nextSetBit(s + BITS_PER_SYMBOL)) {
cleanSymbol.accept(s + LONGBITS);
}
}
@@ -131,6 +214,6 @@ public class LexicalScope {
* @return the number of symbols defined in this scope.
*/
public int getSymbolCount() {
- return Long.bitCount(symbols) + (moreSymbols == null ? 0 : moreSymbols.cardinality());
+ return count;
}
}
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Scope.java b/src/main/java/org/apache/commons/jexl3/internal/Scope.java
index 77b045fc..ee14bbd8 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Scope.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Scope.java
@@ -66,10 +66,6 @@ public final class Scope {
* The map of local captured variables to parent scope variables, ie closure.
*/
private Map<Integer, Integer> capturedVariables = null;
- /**
- * Const symbols.
- */
- private LexicalScope constVariables = null;
/**
* Let symbols.
*/
@@ -178,27 +174,6 @@ public final class Scope {
return lexicalVariables != null && s >= 0 && lexicalVariables.hasSymbol(s);
}
- /**
- * Marks a symbol as a const.
- * @param s the symbol
- * @return true if the symbol was not already present in the constant set
- */
- public boolean addConstant(int s) {
- if (constVariables == null) {
- constVariables = new LexicalScope();
- }
- return constVariables.addSymbol(s);
- }
-
- /**
- * Checks whether a symbol is declared through a const.
- * @param s the symbol
- * @return true if symbol was declared through const
- */
- public boolean isConstant(int s) {
- return constVariables != null && s >= 0 && constVariables.hasSymbol(s);
- }
-
/**
* Checks whether a given symbol is captured.
* @param symbol the symbol number
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java b/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
index 944b5915..88748750 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifier.java
@@ -34,6 +34,8 @@ public class ASTIdentifier extends JexlNode {
private static final int LEXICAL = 3;
/** The const variable flag. */
private static final int CONST = 4;
+ /** The defined variable flag. */
+ private static final int DEFINED = 5;
ASTIdentifier(final int id) {
super(id);
@@ -125,6 +127,14 @@ public class ASTIdentifier extends JexlNode {
flags = set(CONST, flags, f);
}
+ public boolean isDefined() {
+ return isSet(DEFINED, flags);
+ }
+
+ public void setDefined(final boolean f) {
+ flags = set(DEFINED, flags, f);
+ }
+
public String getName() {
return name;
}
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlLexicalNode.java b/src/main/java/org/apache/commons/jexl3/parser/JexlLexicalNode.java
index 8d1a5f17..475f11cc 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlLexicalNode.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlLexicalNode.java
@@ -23,7 +23,7 @@ import org.apache.commons.jexl3.internal.LexicalScope;
* @since 3.2
*/
public class JexlLexicalNode extends JexlNode implements JexlParser.LexicalUnit {
- private LexicalScope locals = null;
+ private LexicalScope lexicalScope = null;
public JexlLexicalNode(final int id) {
super(id);
@@ -35,24 +35,50 @@ public class JexlLexicalNode extends JexlNode implements JexlParser.LexicalUnit
@Override
public boolean declareSymbol(final int symbol) {
- if (locals == null) {
- locals = new LexicalScope();
+ if (lexicalScope == null) {
+ lexicalScope = new LexicalScope();
}
- return locals.addSymbol(symbol);
+ return lexicalScope.addSymbol(symbol);
+ }
+
+ @Override
+ public boolean isConstant(final int symbol) {
+ return lexicalScope != null && lexicalScope.isConstant(symbol);
+ }
+
+ @Override
+ public boolean isDefined(final int symbol) {
+ return lexicalScope != null && lexicalScope.isDefined(symbol);
+ }
+
+ @Override
+ public void setConstant(int symbol) {
+ lexicalScope.addConstant(symbol);
+ }
+
+ @Override
+ public void setDefined(int symbol) {
+ lexicalScope.defineSymbol(symbol);
}
@Override
public int getSymbolCount() {
- return locals == null? 0 : locals.getSymbolCount();
+ return lexicalScope == null? 0 : lexicalScope.getSymbolCount();
}
@Override
public boolean hasSymbol(final int symbol) {
- return locals != null && locals.hasSymbol(symbol);
+ return lexicalScope != null && lexicalScope.hasSymbol(symbol);
}
@Override
public LexicalScope getLexicalScope() {
- return locals;
+ return lexicalScope;
+ }
+
+
+ @Override
+ public void jjtClose() {
+
}
}
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
index 615de42b..7f971216 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
@@ -26,7 +26,6 @@ import org.apache.commons.jexl3.internal.Scope;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
-import java.lang.reflect.Constructor;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
@@ -99,6 +98,8 @@ public abstract class JexlParser extends StringParser {
* @return true if declaration was successful, false if symbol was already declared
*/
boolean declareSymbol(int symbol);
+ void setConstant(int symbol);
+ void setDefined(int symbol);
/**
* Checks whether a symbol is declared in this lexical unit.
@@ -106,6 +107,8 @@ public abstract class JexlParser extends StringParser {
* @return true if declared, false otherwise
*/
boolean hasSymbol(int symbol);
+ boolean isConstant(int symbol);
+ boolean isDefined(int symbol);
/**
* @return the number of local variables declared in this unit
@@ -313,32 +316,41 @@ public abstract class JexlParser extends StringParser {
final Integer symbol = scope.getSymbol(name);
if (symbol != null) {
identifier.setLexical(scope.isLexical(symbol));
- identifier.setConstant(scope.isConstant(symbol));
boolean declared = true;
if (scope.isCapturedSymbol(symbol)) {
// captured are declared in all cases
identifier.setCaptured(true);
} else {
- declared = block.hasSymbol(symbol);
+ LexicalUnit unit = block;
+ declared = unit.hasSymbol(symbol);
// one of the lexical blocks above should declare it
if (!declared) {
for (final LexicalUnit u : blocks) {
if (u.hasSymbol(symbol)) {
+ unit = u;
declared = true;
break;
}
}
}
- if (!declared && info instanceof JexlNode.Info) {
+ if (declared) {
+ if (unit.isConstant(symbol)) {
+ identifier.setConstant(true);
+ if (!unit.isDefined(symbol)) {
+ throw new JexlException.Parsing(info, name + ": variable is not defined").clean();
+ }
+ identifier.setDefined(true);
+ }
+ } else if (info instanceof JexlNode.Info) {
declared = isSymbolDeclared((JexlNode.Info) info, symbol);
}
}
identifier.setSymbol(symbol, name);
if (!declared) {
identifier.setShaded(true);
- if (identifier.isLexical() || getFeatures().isLexicalShade()) {
+ if (/*identifier.isLexical() ||*/ getFeatures().isLexicalShade()) {
// can not reuse a local as a global
- throw new JexlException.Parsing(info, name + ": variable is not defined").clean();
+ throw new JexlException.Parsing(info, name + ": variable is not declared").clean();
}
}
}
@@ -386,7 +398,7 @@ public abstract class JexlParser extends StringParser {
* @param variable the identifier used to declare
* @param token the variable name toekn
*/
- protected void declareFunction(final ASTVar variable, final Token token, Scope scope) {
+ protected void declareFunction(final ASTVar variable, final Token token) {
final String name = token.image;
// function foo() ... <=> const foo = ()->...
if (scope == null) {
@@ -394,11 +406,16 @@ public abstract class JexlParser extends StringParser {
}
final int symbol = scope.declareVariable(name, true, true);
variable.setSymbol(symbol, name);
+ variable.setLexical(true);
if (scope.isCapturedSymbol(symbol)) {
variable.setCaptured(true);
}
- // lexical feature error
- if (!declareSymbol(symbol)) {
+ // function is const fun...
+ if (declareSymbol(symbol)) {
+ scope.addLexical(symbol);
+ block.setConstant(symbol);
+ block.setDefined(symbol);
+ } else {
if (getFeatures().isLexical()) {
throw new JexlException(variable, name + ": variable is already declared");
}
@@ -440,7 +457,7 @@ public abstract class JexlParser extends StringParser {
if (lexical) {
scope.addLexical(symbol);
if (constant) {
- scope.addConstant(symbol);
+ block.setConstant(symbol);
}
}
}
@@ -472,7 +489,8 @@ public abstract class JexlParser extends StringParser {
} else if (lexical) {
scope.addLexical(symbol);
if (constant) {
- scope.addConstant(symbol);
+ block.setConstant(symbol);
+ block.setDefined(symbol); // worst case is no argument, parameter will bind to null
}
}
}
@@ -612,10 +630,17 @@ public abstract class JexlParser extends StringParser {
}
if (lv instanceof ASTIdentifier) {
ASTIdentifier var = (ASTIdentifier) lv;
- if (!(var instanceof ASTVar)) { // if not a declaration...
- int symbol = var.getSymbol();
- if (symbol >= 0 && scope.isConstant(symbol)) {
- throw new JexlException.Assignment(var.jexlInfo(), var.getName()).clean();
+ int symbol = var.getSymbol();
+ boolean isconst = symbol >= 0 && block != null && block.isConstant(symbol);
+ if (isconst) {
+ if (!(var instanceof ASTVar)) { // if not a declaration...
+ if (block.isDefined(symbol)) {
+ throw new JexlException.Assignment(var.jexlInfo(), var.getName()).clean();
+ } else {
+ block.setDefined(symbol);
+ }
+ } else {
+ block.setDefined(symbol);
}
}
}
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index bfc476e6..af16272a 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -455,12 +455,12 @@ void DeclareVar(boolean lexical, boolean constant) #Var :
{
t=<IDENTIFIER> { declareVariable(jjtThis, t, lexical, constant); }
}
-void DeclareFunction(Scope scope) #Var :
+void DeclareFunction() #Var :
{
Token t;
}
{
- t=<IDENTIFIER> { declareFunction(jjtThis, t, scope); }
+ t=<IDENTIFIER> { declareFunction(jjtThis, t); }
}
void Pragma() #void :
@@ -898,15 +898,14 @@ void Lambda() #JexlLambda :
{
Token arrow;
Token name;
- Scope scope = getScope();
- pushScope();
}
{
- { pushUnit(jjtThis); } <FUNCTION> (LOOKAHEAD(<IDENTIFIER>) DeclareFunction(scope))? Parameters() ( LOOKAHEAD(3) Block() | Expression()) { popUnit(jjtThis); popScope(); }
+ <FUNCTION> (LOOKAHEAD(<IDENTIFIER>) DeclareFunction())? {
+ pushScope(); pushUnit(jjtThis); } Parameters() ( LOOKAHEAD(3) Block() | Expression()) { popUnit(jjtThis); popScope(); }
|
- { pushUnit(jjtThis); } Parameters() (arrow=<LAMBDA> | arrow=<FATARROW>) ( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); }
+ { pushScope(); pushUnit(jjtThis); } Parameters() (arrow=<LAMBDA> | arrow=<FATARROW>) ( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); }
|
- { pushUnit(jjtThis); } Parameter() (arrow=<LAMBDA> | arrow=<FATARROW>)( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); }
+ { pushScope(); pushUnit(jjtThis); } Parameter() (arrow=<LAMBDA> | arrow=<FATARROW>)( LOOKAHEAD(3) Block() | Expression()) { checkLambda(arrow); popUnit(jjtThis); popScope(); }
}
diff --git a/src/test/java/org/apache/commons/jexl3/LambdaTest.java b/src/test/java/org/apache/commons/jexl3/LambdaTest.java
index ea32a7e9..de7dab86 100644
--- a/src/test/java/org/apache/commons/jexl3/LambdaTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LambdaTest.java
@@ -437,11 +437,36 @@ public class LambdaTest extends JexlTestCase {
Assert.assertEquals(simpleWhitespace(src), parsed);
}
+ @Test
+ public void testConst0() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ final JexlScript script = jexl.createScript(
+ "{ const x = 10; x + 1 }; { let x = 20; x = 22}");
+ final JexlContext jc = new MapContext();
+ final Object result = script.execute(jc);
+ Assert.assertEquals(22, result);
+ }
+
+ @Test
+ public void testConst1() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ try {
+ final JexlScript script = jexl.createScript(
+ "const x; x + 1");
+ Assert.fail("should fail, x is not defined");
+ } catch(JexlException.Parsing xparse) {
+ Assert.assertTrue(xparse.getMessage().contains("x"));
+ }
+ }
+
@Test public void testNamedFuncIsConst() {
String src = "function foo(x) { x + x }; var foo ='nonononon'";
JexlEngine jexl = createEngine();
try {
JexlScript script = jexl.createScript(src);
+ Assert.fail("should fail, foo is already defined");
} catch(JexlException.Parsing xparse) {
Assert.assertTrue(xparse.getMessage().contains("foo"));
}
diff --git a/src/test/java/org/apache/commons/jexl3/LexicalTest.java b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
index 058050fe..9271c554 100644
--- a/src/test/java/org/apache/commons/jexl3/LexicalTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
@@ -29,6 +29,8 @@ import org.apache.commons.jexl3.internal.Script;
import org.junit.Assert;
import org.junit.Test;
+import static org.apache.commons.jexl3.JexlTestCase.createEngine;
+
/**
* Test cases for lexical option and feature.
*/
@@ -525,7 +527,10 @@ public class LexicalTest {
@Test
public void testForVariable0a() {
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ final JexlFeatures f = new JexlFeatures();
+ f.lexical(true);
+ f.lexicalShade(true);
+ final JexlEngine jexl = createEngine(f);
try {
final JexlScript script = jexl.createScript("for(let x : 1..3) { let c = 0}; return x");
Assert.fail("Should not have been parsed");
@@ -539,7 +544,7 @@ public class LexicalTest {
final JexlFeatures f = new JexlFeatures();
f.lexical(true);
f.lexicalShade(true);
- final JexlEngine jexl = new JexlBuilder().strict(true).features(f).create();
+ final JexlEngine jexl = createEngine(f);
try {
final JexlScript script = jexl.createScript("for(var x : 1..3) { var c = 0}; return x");
Assert.fail("Should not have been parsed");
@@ -553,7 +558,7 @@ public class LexicalTest {
final JexlFeatures f = new JexlFeatures();
f.lexical(true);
f.lexicalShade(true);
- final JexlEngine jexl = new JexlBuilder().strict(true).features(f).create();
+ final JexlEngine jexl = createEngine(f);
try {
final JexlScript script = jexl.createScript("for(var x : 1..3) { var c = 0} for(var x : 1..3) { var c = 0}; return x");
Assert.fail("Should not have been parsed");
@@ -565,7 +570,10 @@ public class LexicalTest {
@Test
public void testForVariable1b() {
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ final JexlFeatures f = new JexlFeatures();
+ f.lexical(true);
+ f.lexicalShade(true);
+ final JexlEngine jexl = createEngine(f);
try {
final JexlScript script = jexl.createScript("for(let x : 1..3) { let c = 0} for(let x : 1..3) { var c = 0}; return x");
Assert.fail("Should not have been parsed");
@@ -580,7 +588,7 @@ public class LexicalTest {
final JexlFeatures f = new JexlFeatures();
f.lexical(true);
f.lexicalShade(true);
- final JexlEngine jexl = new JexlBuilder().strict(true).features(f).create();
+ final JexlEngine jexl = createEngine(f);
try {
final JexlScript script = jexl.createScript("{var x = 0}; return x");
Assert.fail("Should not have been parsed");
@@ -595,7 +603,7 @@ public class LexicalTest {
final String str = "i = 0; { var i = 32; }; i";
final JexlFeatures f = new JexlFeatures();
f.lexical(true);
- final JexlEngine jexl = new JexlBuilder().strict(true).features(f).create();
+ final JexlEngine jexl = createEngine(f);
final JexlScript e = jexl.createScript(str);
final JexlContext ctxt = new MapContext();
final Object o = e.execute(ctxt);