You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by at...@apache.org on 2016/01/02 16:11:39 UTC
commons-scxml git commit: SCXML-245: Reimplement Nashorn Javascript
Evaluator - See: https://issues.apache.org/jira/browse/SCXML-245 for details
Repository: commons-scxml
Updated Branches:
refs/heads/master 031f8ff32 -> 1b91a77c1
SCXML-245: Reimplement Nashorn Javascript Evaluator
- See: https://issues.apache.org/jira/browse/SCXML-245 for details
Project: http://git-wip-us.apache.org/repos/asf/commons-scxml/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-scxml/commit/1b91a77c
Tree: http://git-wip-us.apache.org/repos/asf/commons-scxml/tree/1b91a77c
Diff: http://git-wip-us.apache.org/repos/asf/commons-scxml/diff/1b91a77c
Branch: refs/heads/master
Commit: 1b91a77c1a41a57799da93ce0ba3a4b58760148e
Parents: 031f8ff
Author: Ate Douma <at...@apache.org>
Authored: Sat Jan 2 16:11:30 2016 +0100
Committer: Ate Douma <at...@apache.org>
Committed: Sat Jan 2 16:11:30 2016 +0100
----------------------------------------------------------------------
pom.xml | 9 +
.../scxml2/env/javascript/JSBindings.java | 277 ++------
.../scxml2/env/javascript/JSContext.java | 15 +-
.../scxml2/env/javascript/JSEvaluator.java | 192 ++++--
.../scxml2/env/javascript/JSFunctions.java | 50 --
.../scxml2/env/javascript/init_global.js | 142 ++++
.../scxml2/env/javascript/JSBindingsTest.java | 669 -------------------
.../env/javascript/JavaScriptEngineTest.java | 108 +--
.../org/apache/commons/scxml2/w3c/tests.xml | 14 +-
9 files changed, 390 insertions(+), 1086 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 06d3a65..a6bf606 100644
--- a/pom.xml
+++ b/pom.xml
@@ -204,6 +204,15 @@
<build>
<sourceDirectory>src/main/java</sourceDirectory>
+ <resources>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.js</include>
+ </includes>
+ </resource>
+ </resources>
<testSourceDirectory>src/test/java</testSourceDirectory>
<testResources>
<testResource>
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/main/java/org/apache/commons/scxml2/env/javascript/JSBindings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSBindings.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSBindings.java
index 6b7142f..dc9ab7c 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSBindings.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSBindings.java
@@ -18,339 +18,154 @@
package org.apache.commons.scxml2.env.javascript;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.script.Bindings;
-import javax.script.SimpleBindings;
import org.apache.commons.scxml2.Context;
/**
- * Wrapper class for the JDK Javascript engine Bindings class that extends the
- * wrapped Bindings to search the SCXML context for variables and predefined
- * functions that do not exist in the wrapped Bindings.
- *
+ * JDK Javascript engine Bindings class that delegates to a SCXML context
*/
public class JSBindings implements Bindings {
- private static final String NASHORN_GLOBAL = "nashorn.global";
-
- // INSTANCE VARIABLES
-
- private Bindings bindings;
- private Context context;
-
- // CONSTRUCTORS
+ private JSContext context;
/**
- * Initialises the internal Bindings delegate and SCXML context.
+ * Initialise the Bindings
*
- * @param context SCXML Context to use for script variables.
- * @param bindings Javascript engine bindings for Javascript variables.
+ * @param jsContext initial SCXML Context to use for script variables.
*
- * @throws IllegalArgumentException Thrown if either <code>context</code>
- * or <code>bindings</code> is <code>null</code>.
+ * @throws IllegalArgumentException Thrown if <code>jsContext</code> is <code>null</code>.
*
*/
- public JSBindings(Context context, Bindings bindings) {
- // ... validate
-
- if (context == null) {
- throw new IllegalArgumentException("Invalid SCXML context");
- }
+ public JSBindings(JSContext jsContext) {
+ setContext(jsContext);
+ }
- if (bindings == null) {
- throw new IllegalArgumentException("Invalid script Bindings");
+ /**
+ * Set or update the SCXML context delegate
+ *
+ * @param jsContext the SCXML context to use for script variables.
+ * @throws IllegalArgumentException Thrown if <code>jsContext</code> is <code>null</code>.
+ */
+ public void setContext(JSContext jsContext) {
+ if (jsContext == null) {
+ throw new IllegalArgumentException("SCXML context is required");
}
-
- // ... initialise
-
- this.bindings = bindings;
- this.context = context;
+ this.context = jsContext;
}
- // INSTANCE METHODS
-
/**
- * Returns <code>true</code> if the wrapped Bindings delegate
- * or SCXML context contains a variable identified by
- * <code>key</code>.
- *
+ * Returns <code>true</code> if the SCXML context contains a variable identified by <code>key</code>.
*/
@Override
public boolean containsKey(Object key) {
- if (hasGlobalBindings() && getGlobalBindings().containsKey(key)) {
- return true;
- }
-
- if (bindings.containsKey(key)) {
- return true;
- }
-
return context.has(key.toString());
}
/**
- * Returns a union of the wrapped Bindings entry set and the
- * SCXML context entry set.
- * <p>
- * NOTE: doesn't seem to be invoked ever. Not thread-safe.
- *
+ * Returns the SCXML context key set
*/
@Override
public Set<String> keySet() {
- Set<String> keys = new HashSet<String>();
-
- keys.addAll(context.getVars().keySet());
- keys.addAll(bindings.keySet());
-
- if (hasGlobalBindings()) {
- keys.addAll(getGlobalBindings().keySet());
- }
-
- return keys;
+ return context.getVars().keySet();
}
/**
- * Returns the combined size of the wrapped Bindings entry set and the
- * SCXML context entry set.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
- *
+ * Returns the size of the SCXML context size.
*/
@Override
public int size() {
- Set<String> keys = new HashSet<String>();
-
- keys.addAll(context.getVars().keySet());
- keys.addAll(bindings.keySet());
-
- if (hasGlobalBindings()) {
- keys.addAll(getGlobalBindings().keySet());
- }
-
- return keys.size();
+ return context.getVars().size();
}
/**
- * Returns <code>true</code> if the wrapped Bindings delegate
- * or SCXML context contains <code>value</code>.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Returns <code>true</code> if the SCXML context contains <code>value</code>.
*/
@Override
public boolean containsValue(Object value) {
- if (hasGlobalBindings() && getGlobalBindings().containsValue(value)) {
- return true;
- }
-
- if (bindings.containsValue(value)) {
- return true;
- }
-
return context.getVars().containsValue(value);
}
/**
- * Returns a union of the wrapped Bindings entry set and the
- * SCXML context entry set.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Returns the SCXML context entry set.
*/
@Override
public Set<Map.Entry<String,Object>> entrySet() {
- return union().entrySet();
+ return context.getVars().entrySet();
}
/**
- * Returns a union of the wrapped Bindings value list and the
- * SCXML context value list.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Returns the SCXML context values.
*/
@Override
public Collection<Object> values() {
- return union().values();
+ return context.getVars().values();
}
/**
- * Returns a <code>true</code> if both the Bindings delegate and
- * the SCXML context maps are empty.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Returns <code>true</code> if the SCXML context is empty.
*/
@Override
public boolean isEmpty() {
- if (hasGlobalBindings() && !getGlobalBindings().isEmpty()) {
- return false;
- }
-
- if (!bindings.isEmpty()) {
- return false;
- }
-
return context.getVars().isEmpty();
}
/**
- * Returns the value from the wrapped Bindings delegate
- * or SCXML context contains identified by <code>key</code>.
- *
+ * Returns the value from the SCXML context identified by <code>key</code>.
*/
@Override
public Object get(Object key) {
- // nashorn.global should be retrieved from the bindings, not from context.
- if (NASHORN_GLOBAL.equals(key)) {
- return bindings.get(key);
- }
-
- if (hasGlobalBindings() && getGlobalBindings().containsKey(key)) {
- return getGlobalBindings().get(key);
- }
-
- if (bindings.containsKey(key)) {
- return bindings.get(key);
- }
-
return context.get(key.toString());
}
/**
* The following delegation model is used to set values:
* <ol>
- * <li>Delegates to {@link Context#set(String,Object)} if the
- * {@link Context} contains the key (name), else</li>
- * <li>Delegates to the wrapped {@link Bindings#put(String, Object)}
- * if the {@link Bindings} contains the key (name), else</li>
+ * <li>Delegates to {@link Context#set(String,Object)} if the Context contains the key (name), else</li>
* <li>Delegates to {@link Context#setLocal(String, Object)}</li>
* </ol>
- *
+ * @param name The variable name
+ * @param value The variable value
*/
@Override
public Object put(String name, Object value) {
- Object old = context.get(name);
-
- // nashorn.global should be put into the bindings, not into context.
- if (NASHORN_GLOBAL.equals(name)) {
- return bindings.put(name, value);
- } else if (context.has(name)) {
+ Object old = null;
+ if (context.has(name)) {
+ old = context.get(name);
context.set(name, value);
- } else if (bindings.containsKey(name)) {
- return bindings.put(name, value);
- } else if (hasGlobalBindings() && getGlobalBindings().containsKey(name)) {
- return getGlobalBindings().put(name, value);
} else {
context.setLocal(name, value);
}
-
return old;
}
/**
- * Delegates to the wrapped Bindings <code>putAll</code> method i.e. does
- * not store variables in the SCXML context.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Sets all entries in the provided map via {@link #put(String, Object)}
+ * @param toMerge the map of variables to merge
*/
@Override
public void putAll(Map<? extends String, ? extends Object> toMerge) {
- bindings.putAll(toMerge);
+ for (Map.Entry<? extends String, ? extends Object> entry : toMerge.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
}
/**
- * Removes the object from the wrapped Bindings instance or the contained
- * SCXML context. Not entirely sure about this implementation but it
- * follows the philosophy of using the Javascript Bindings as a child context
- * of the SCXML context.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Removes the named variable from the contained SCXML context.
+ * @param name the variable name
*/
@Override
- public Object remove(Object key) {
- if (hasGlobalBindings() && getGlobalBindings().containsKey(key)) {
- getGlobalBindings().remove(key);
- }
-
- if (bindings.containsKey(key)) {
- return bindings.remove(key);
- }
-
- if (context.has(key.toString())) {
- return context.getVars().remove(key);
- }
-
- return Boolean.FALSE;
+ public Object remove(Object name) {
+ return context.getVars().remove(name);
}
/**
- * Delegates to the wrapped Bindings <code>clear</code> method. Does not clear
- * the SCXML context.
- * <p>
- * NOTE: doesn't seem to be invoked ever so not sure if it works in
- * context. Not thread-safe.
+ * Does nothing - never invoked anyway
*/
@Override
public void clear() {
- bindings.clear();
- }
-
- /**
- * Internal method to create a union of the SCXML context and the Javascript
- * Bindings. Does a heavyweight copy - and so far only invoked by the
- * not used methods.
- */
- private Bindings union() {
- Bindings set = new SimpleBindings();
-
- set.putAll(context.getVars());
-
- for (String key : bindings.keySet()) {
- set.put(key, bindings.get(key));
- }
-
- if (hasGlobalBindings()) {
- for (String key : getGlobalBindings().keySet()) {
- set.put(key, getGlobalBindings().get(key));
- }
- }
-
- return set;
- }
-
- /**
- * Return true if a global bindings (i.e. nashorn Global instance) was ever set by the script engine.
- * <p>
- * Note: because the global binding can be set by the script engine when evaluating a script, we should
- * check or retrieve the global binding whenever needed instead of initialization time.
- * </p>
- * @return true if a global bindings (i.e. nashorn Global instance) was ever set by the script engine
- */
- protected boolean hasGlobalBindings() {
- if (bindings.containsKey(NASHORN_GLOBAL)) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Return the global bindings (i.e. nashorn Global instance) set by the script engine if existing.
- * @return the global bindings (i.e. nashorn Global instance) set by the script engine, or null if not existing.
- */
- protected Bindings getGlobalBindings() {
- if (bindings.containsKey(NASHORN_GLOBAL)) {
- return (Bindings) bindings.get(NASHORN_GLOBAL);
- }
-
- return null;
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/main/java/org/apache/commons/scxml2/env/javascript/JSContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSContext.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSContext.java
index d63d25a..f1b063c 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSContext.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSContext.java
@@ -27,26 +27,21 @@ import org.apache.commons.scxml2.env.SimpleContext;
* extension of SimpleContext that has been implemented to reduce the impact
* if the JSEvaluator requires additional functionality at a later stage.
* <p>
- * Could easily be dispensed with.
- *
*/
public class JSContext extends SimpleContext {
/** Serial version UID. */
private static final long serialVersionUID = 1L;
- // CONSTRUCTORS
-
/**
- * Default constructor - just invokes the SimpleContext default
- * constructor.
+ * Default constructor - just invokes the SimpleContext default constructor.
*/
public JSContext() {
super();
}
/**
- * Constructor with initial vars.
+ * Constructor with initial vars - Just invokes the identical SimpleContext constructor.
* @param parent The parent context
* @param initialVars The initial set of variables.
*/
@@ -55,15 +50,11 @@ public class JSContext extends SimpleContext {
}
/**
- * Child constructor. Just invokes the identical SimpleContext
- * constructor.
- *
+ * Child constructor - Just invokes the identical SimpleContext constructor.
* @param parent Parent context for this context.
- *
*/
public JSContext(final Context parent) {
super(parent);
}
-
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
index 2f9641d..d71933e 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
@@ -17,14 +17,17 @@
package org.apache.commons.scxml2.env.javascript;
+import java.io.IOException;
import java.util.UUID;
-import java.util.regex.Pattern;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.EvaluatorProvider;
@@ -34,11 +37,21 @@ import org.apache.commons.scxml2.env.EffectiveContextMap;
import org.apache.commons.scxml2.model.SCXML;
/**
- * Embedded JavaScript expression evaluator for SCXML expressions. This
- * implementation is a just a 'thin' wrapper around the Javascript engine in
- * JDK 8.
+ * Embedded JavaScript expression evaluator for SCXML expressions using the JDK 8+ Nashorn Script Engine.
+ * <p>
+ * Each JSEvaluator maintains a single {@link ScriptContext} instance to be used for only a single SCXML instance as
+ * the Nashorn global state is shared through the {@link ScriptContext#ENGINE_SCOPE} binding.
+ * </p>
+ * <p>Sharing and reusing JSEvaluator instances for multiple SCXML instances therefore should <em>not</em> be done.</p>
+ * <p>
+ * As the JDK Script Engine state is <em>not</em> serializable, and neither are Javascript <code>native</code> Objects,
+ * the {@link ScriptContext} state is <em>not</em> retained during serialization (transient).
+ * </p>
+ * <p>
+ * SCXML instance (de)serialization using the javascript language therefore only will work reliably as long as no
+ * Javascript native Objects are used/stored in the context nor (other) modifications are made to the Nashorn global state.
+ * </p>
*/
-
public class JSEvaluator extends AbstractBaseEvaluator {
/**
@@ -66,33 +79,98 @@ public class JSEvaluator extends AbstractBaseEvaluator {
}
}
+ private static final String SCXML_SYSTEM_CONTEXT = "_scxmlSystemContext";
+
/** Error message if evaluation context is not a JexlContext. */
private static final String ERR_CTX_TYPE = "Error evaluating JavaScript "
+ "expression, Context must be a org.apache.commons.scxml2.env.javascript.JSContext";
- /** Pattern for recognizing the SCXML In() special predicate. */
- private static final Pattern IN_FN = Pattern.compile("In\\(");
+ /** shared singleton Nashorn ScriptEngine **/
+ private static ScriptEngine engine;
- // INSTANCE VARIABLES
+ /** Nashorn Global initialization script, loaded from <code>init_global.js</code> classpath resource */
+ private static String initGlobalsScript;
- private transient ScriptEngineManager factory;
-
- // CONSTRUCTORS
+ /** ScriptContext for a single SCXML instance (JSEvaluator also cannot be shared between SCXML instances) */
+ private transient ScriptContext scriptContext;
/**
- * Initialises the internal Javascript engine factory.
+ * Initialize the singleton Javascript ScriptEngine to be used with a separate ScriptContext for each SCXML instance
+ * not sharing their global scope, see {@link #getScriptContext(JSContext)}.
+ * <p>
+ * The SCXML required protected system variables and (possible) other Javascript global initializations are defined
+ * in a <code>init_global.js</code> script which is pre-loaded as (classpath) resource, to be executed once during
+ * initialization of a new Javascript (Nashorn) Global.
+ * </p>
*/
- public JSEvaluator() {
- factory = new ScriptEngineManager();
+ protected synchronized static void initEngine() {
+ if (engine == null) {
+ engine = new ScriptEngineManager().getEngineByName("JavaScript");
+ try {
+ initGlobalsScript = IOUtils.toString(JSEvaluator.class.getResourceAsStream("init_global.js"), "UTF-8");
+ }
+ catch (IOException ioe) {
+ throw new RuntimeException("Failed to load init_global.js from classpath", ioe);
+ }
+ }
}
- // INSTANCE METHODS
+ /**
+ * Get the singleton ScriptEngine, initializing it on first access
+ * @return The ScriptEngine
+ */
+ protected ScriptEngine getEngine() {
+ if (engine == null) {
+ initEngine();
+ }
+ return engine;
+ }
- protected ScriptEngineManager getFactory() {
- if (factory == null) {
- factory = new ScriptEngineManager();
+ /**
+ * Get the current ScriptContext or create a new one.
+ * <p>
+ * The ScriptContext is (to be) shared across invocations for the same SCXML instance as it holds the Javascript 'global'
+ * context.
+ * </p>
+ * <p>
+ * The ScriptContext is using a {@link ScriptContext#ENGINE_SCOPE} as provided by the engine, which in case of Nashorn
+ * is bound to the Javscript global context. Note: do <em>not</em> confuse this with the {@link ScriptContext#GLOBAL_SCOPE} binding.
+ * </p>
+ * <p>For a newly created ScriptContext (and thus a new Javascript global context), the Javascript global context is
+ * initialized with the required and protected SCXML system variables and builtin In() operator via the
+ * <code>init_global.js</code> script, loaded as classpath resource.</p>
+ * <p>
+ * The SCXML system variables are bound as <code>"_scxmlSystemContext"</code> variable in the ENGINE_SCOPE
+ * as needed for the <code>init_global.js</code> script in the global context.
+ * This variable is bound to the ENGINE_SCOPE to ensure it cannot be 'shadowed' by an overriding variable assignment.
+ * </p>
+ * The provided SCXML Context variables are bound via the GLOBAL_SCOPE using a {@link JSBindings} wrapper for each
+ * invocation.
+ * </p>
+ * <p>
+ * As the GLOBAL_SCOPE SCXML context variables <em>can</em> be overridden, which will result in new 'shadow'
+ * variables in the ENGINE_SCOPE, as well as new variables can be added to the ENGINE_SCOPE during script evaluation,
+ * after script execution all ENGINE_SCOPE variables (except the <code>"_scxmlSystemContext"</code> variable) must be
+ * copied/merged into the SCXML context to synchronize the SCXML context.
+ * </p>
+ * @param jsContext The current SCXML context
+ * @return The SCXML instance shared ScriptContext
+ * @throws ScriptException Thrown if the initialization of the Global Javascript engine itself failed
+ */
+ protected ScriptContext getScriptContext(JSContext jsContext) throws ScriptException {
+ if (scriptContext == null) {
+ scriptContext = new SimpleScriptContext();
+ scriptContext.setBindings(getEngine().createBindings(), ScriptContext.ENGINE_SCOPE);
+ scriptContext.setBindings(new JSBindings(jsContext), ScriptContext.GLOBAL_SCOPE);
+ scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(SCXML_SYSTEM_CONTEXT, jsContext.getSystemContext().getVars());
+ getEngine().eval(initGlobalsScript, scriptContext);
+ }
+ else {
+ // ensure updated / replaced SystemContext is used (like after SCXML instance go/reset)
+ scriptContext.getBindings(ScriptContext.ENGINE_SCOPE).put(SCXML_SYSTEM_CONTEXT, jsContext.getSystemContext().getVars());
+ ((JSBindings)scriptContext.getBindings(ScriptContext.GLOBAL_SCOPE)).setContext(jsContext);
}
- return factory;
+ return scriptContext;
}
@Override
@@ -121,50 +199,32 @@ public class JSEvaluator extends AbstractBaseEvaluator {
}
/**
- * Evaluates the expression using a new Javascript engine obtained from
- * factory instantiated in the constructor. The engine is supplied with
- * a new JSBindings that includes the SCXML Context and SCXML builtin
- * <code>In()</code> function is replaced with an equivalent internal
- * Javascript function.
- *
+ * Evaluates a Javascript expression using an SCXML instance shared {@link #getScriptContext(JSContext)}.
+ * <p>
+ * After evaluation all the resulting Javascript Global context (in {@link ScriptContext#ENGINE_SCOPE} are first
+ * copied/merged back into the SCXML context, before the evaluation result (if any) is returned.
+ * </p>
* @param context SCXML context.
* @param expression Expression to evaluate.
- *
* @return Result of expression evaluation or <code>null</code>.
- *
- * @throws SCXMLExpressionException Thrown if the expression was invalid.
+ * @throws SCXMLExpressionException Thrown if the expression was invalid or the execution raised an error itself.
*/
@Override
public Object eval(Context context, String expression) throws SCXMLExpressionException {
if (expression == null) {
return null;
}
-
if (!(context instanceof JSContext)) {
throw new SCXMLExpressionException(ERR_CTX_TYPE);
}
try {
- JSContext effectiveContext = getEffectiveContext((JSContext) context);
-
- // ... initialize
- ScriptEngine engine = getFactory().getEngineByName("JavaScript");
- Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
-
- // ... replace built-in functions
- String jsExpression = IN_FN.matcher(expression).replaceAll("_builtin.In(");
-
- // ... evaluate
- JSBindings jsBindings = new JSBindings(effectiveContext, bindings);
- jsBindings.put("_builtin", new JSFunctions(effectiveContext));
-
- Object ret = engine.eval(jsExpression, jsBindings);
-
- // copy global bindings attributes to context, so callers may get access to the evaluated variables.
- copyGlobalBindingsToContext(jsBindings, effectiveContext);
-
+ JSContext effectiveContext = getEffectiveContext((JSContext)context);
+ ScriptContext scriptContext = getScriptContext(effectiveContext);
+ Object ret = getEngine().eval(expression, scriptContext);
+ // copy Javascript global variables to SCXML context.
+ copyJavascriptGlobalsToScxmlContext(scriptContext.getBindings(ScriptContext.ENGINE_SCOPE), effectiveContext);
return ret;
-
} catch (Exception x) {
throw new SCXMLExpressionException("Error evaluating ['" + expression + "'] " + x);
}
@@ -177,10 +237,9 @@ public class JSEvaluator extends AbstractBaseEvaluator {
* @param context SCXML context.
* @param expression Expression to evaluate.
*
- * @return Boolean or <code>null</code>.
+ * @return Boolean casted result.
*
- * @throws SCXMLExpressionException Thrown if the expression was invalid or did
- * not return a boolean.
+ * @throws SCXMLExpressionException Thrown if the expression was invalid.
*/
@Override
public Boolean evalCond(Context context, String expression) throws SCXMLExpressionException {
@@ -202,11 +261,7 @@ public class JSEvaluator extends AbstractBaseEvaluator {
}
/**
- * Executes the script using a new Javascript engine obtained from
- * factory instantiated in the constructor. The engine is supplied with
- * a new JSBindings that includes the SCXML Context and SCXML builtin
- * <code>In()</code> function is replaced with an equivalent internal
- * Javascript function.
+ * Executes the Javascript script using the <code>eval()</code> method
*
* @param ctx SCXML context.
* @param script Script to execute.
@@ -225,8 +280,8 @@ public class JSEvaluator extends AbstractBaseEvaluator {
* current state to document root, child has priority over parent
* in scoping rules.
*
- * @param nodeCtx The JexlContext for this state.
- * @return The effective JexlContext for the path leading up to
+ * @param nodeCtx The JSContext for this state.
+ * @return The effective JSContext for the path leading up to
* document root.
*/
protected JSContext getEffectiveContext(final JSContext nodeCtx) {
@@ -234,18 +289,19 @@ public class JSEvaluator extends AbstractBaseEvaluator {
}
/**
- * Copy the global Bindings (i.e. nashorn Global instance) attributes to {@code jsContext}
- * in order to make sure all the new global variables set by the JavaScript engine after evaluation
+ * Copy the Javscript global context (i.e. nashorn Global instance) variables to SCXML {@code jsContext}
+ * in order to make sure all the new global variables set by the JavaScript engine after evaluation are
* available from {@link JSContext} instance as well.
- * @param jsBindings
- * @param jsContext
+ * <p>Note: the internal <code>"_scxmlSystemContext</code> variable is always skipped.</p>
+ * @param global The Javascript Bindings holding the Javascript Global context variables
+ * @param jsContext The SCXML context to copy/merge the variables into
*/
- private void copyGlobalBindingsToContext(final JSBindings jsBindings, final JSContext jsContext) {
- Bindings globalBindings = jsBindings.getGlobalBindings();
-
- if (globalBindings != null) {
- for (String key : globalBindings.keySet()) {
- jsContext.set(key, globalBindings.get(key));
+ private void copyJavascriptGlobalsToScxmlContext(final Bindings global, final JSContext jsContext) {
+ if (global != null) {
+ for (String key : global.keySet()) {
+ if (!SCXML_SYSTEM_CONTEXT.equals(key)) {
+ jsContext.set(key, global.get(key));
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
deleted file mode 100644
index 45771a0..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSFunctions.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.scxml2.env.javascript;
-
-import java.io.Serializable;
-
-import org.apache.commons.scxml2.Builtin;
-import org.apache.commons.scxml2.Context;
-
-/**
- * Custom Javascript engine function providing the SCXML In() predicate .
- */
-public class JSFunctions implements Serializable {
-
- /**
- * The context currently in use for evaluation.
- */
- private Context ctx;
-
- /**
- * Creates a new instance, wraps the context.
- * @param ctx the context in use
- */
- public JSFunctions(Context ctx) {
- this.ctx = ctx;
- }
-
- /**
- * Provides the SCXML standard In() predicate for SCXML documents.
- * @param state The State ID to compare with
- * @return true if this state is currently active
- */
- public boolean In(final String state) {
- return Builtin.isMember(ctx, state);
- }
-}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js b/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
new file mode 100644
index 0000000..b4cb4fc
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ Define global and protected SCXML system properties and builtin functions,
+ all delegating to _scxmlSystemContext variables map provided as a ScriptEngine binding.
+ The _event object is wrapped in additional (frozen) _scxmlEvent property to provide ECMAScript object semantics.
+ */
+Object.defineProperties(this, {
+ // common method to throw 'protected' error
+ "_scxmlProtected":
+ {
+ get: function() {
+ return function(name) {
+ throw new Error(name+" is a protected SCXML system property")
+ }
+ }
+ },
+ "_name": {
+ get: function () {
+ return _scxmlSystemContext._name
+ },
+ set: function () {
+ _scxmlProtected("_name")
+ }
+ },
+ "_sessionid":
+ {
+ get: function() {
+ return _scxmlSystemContext._sessionid
+ },
+ set: function() {
+ _scxmlProtected("_sessionid")
+ }
+ },
+ "_ioprocessors":
+ {
+ get: function() {
+ return _scxmlSystemContext._ioprocessors
+ },
+ set: function() {
+ _scxmlProtected("_ioprocessors")
+ }
+ },
+ // extra wrapper object needed for _event wrapping as defining this inline
+ // on _event.get method somehow doesn't work properly
+ "_scxmlEvent":
+ {
+ value: {
+ get name() {
+ return _scxmlSystemContext._event.name||undefined
+ },
+ set name(val) {
+ _scxmlProtected("_event.name")
+ },
+ get type() {
+ return _scxmlSystemContext._event.type||undefined
+ },
+ set type(val) {
+ _scxmlProtected("_event.type")
+ },
+ get sendid() {
+ return _scxmlSystemContext._event.sendid||undefined
+ },
+ set sendid(val) {
+ _scxmlProtected("_event.sendid")
+ },
+ get orgin() {
+ return _scxmlSystemContext._event.orgin||undefined
+ },
+ set origin(val) {
+ _scxmlProtected("_event.origin")
+ },
+ get origintype() {
+ return _scxmlSystemContext._event.orgintype||undefined
+ },
+ set origintype(val) {
+ _scxmlProtected("_event.origintype")
+ },
+ get invokeid() {
+ return _scxmlSystemContext._event.invokeid||undefined
+ },
+ set invokeid(val) {
+ _scxmlProtected("_event.invokeid")
+ },
+ get data() {
+ return _scxmlSystemContext._event.data||undefined
+ },
+ set data(val) {
+ _scxmlProtected("_event.data")
+ }
+ },
+ writable : false,
+ configurable : false,
+ enumeratable : false,
+ },
+ "_event":
+ {
+ get: function() {
+ return _scxmlSystemContext._event ? _scxmlEvent : undefined;
+ },
+ set: function() {
+ _scxmlProtected("_event")
+ }
+ },
+ "_x":
+ {
+ get: function() {
+ return _scxmlSystemContext._x
+ },
+ set: function() {
+ _scxmlProtected("_x")
+ }
+ },
+ // required SCXML builtin In() predicate
+ "In":
+ {
+ get: function() {
+ return function(state) {
+ return _scxmlSystemContext._x.status.isInState(state)
+ }
+ },
+ set: function() {
+ _scxmlProtected("_In()")
+ }
+ }
+});
+// ensure extra _scxmlEvent wrapper object is deep protected
+Object.freeze(_scxmlEvent);
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/test/java/org/apache/commons/scxml2/env/javascript/JSBindingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/JSBindingsTest.java b/src/test/java/org/apache/commons/scxml2/env/javascript/JSBindingsTest.java
deleted file mode 100644
index 64447f9..0000000
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/JSBindingsTest.java
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.scxml2.env.javascript;
-
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.scxml2.Context;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import javax.script.Bindings;
-import javax.script.SimpleBindings;
-
-/**
- * JUnit 3 test case for the JSBinding implementation that imports
- * SCXML context variables into a JavaScript bindings. Includes tests
- * for:
- * <ul>
- * <li> constructor
- * </ul>
- */
-public class JSBindingsTest {
- // TEST CONSTANTS
-
- private static final Map.Entry<String,Object> KOALA = new AbstractMap.SimpleEntry<String,Object>("bear","koala");
- private static final Map.Entry<String,Object> GRIZZLY = new AbstractMap.SimpleEntry<String,Object>("bear","grizzly");
- private static final Map.Entry<String,Object> FELIX = new AbstractMap.SimpleEntry<String,Object>("cat", "felix");
- private static final Map.Entry<String,Object> ROVER = new AbstractMap.SimpleEntry<String,Object>("dog", "rover");
-
- // TEST VARIABLES
-
- // TEST SETUP
-
- /**
- * Creates and initializes an SCXML data model in the context.
- */
- @Before
- public void setUp() throws Exception {
- }
-
- // CLASS METHODS
-
- /**
- * Stand-alone test runtime.
- */
- public static void main(String args[]) {
- String[] testCaseName = {JSBindingsTest.class.getName()};
- junit.textui.TestRunner.main(testCaseName);
- }
-
- // INSTANCE METHOD TESTS
-
- /**
- * Tests implementation of JSBindings constructor.
- */
- @Test
- public void testConstructor() {
- Assert.assertNotNull(new JSBindings(new JSContext(),new SimpleBindings()));
- }
-
- /**
- * Test implementation of JSBindings constructor with invalid SCXML context.
- */
- @Test
- public void testInvalidContextConstructor() {
- try {
- Assert.assertNotNull(new JSBindings(null,new SimpleBindings()));
- Assert.fail("JSBindings constructor accepted invalid SCXML context");
-
- } catch (IllegalArgumentException x) {
- // expected, ignore
- }
- }
-
- /**
- * Test implementation of JSBindings constructor with invalid Javascript bindings.
- */
- @Test
- public void testInvalidBindingsConstructor() {
- try {
- Assert.assertNotNull(new JSBindings(new JSContext(),null));
- Assert.fail("JSBindings constructor accepted invalid Javascript bindings");
-
- } catch (IllegalArgumentException x) {
- // expected, ignore
- }
- }
-
- /**
- * Tests the <code>containsKey</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testContainsKey() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertFalse("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse("Invalid Javascript bindings",bindings.containsKey("bear"));
- Assert.assertFalse("Invalid JSbindings", jsx.containsKey ("bear"));
-
- context.set("bear","koala");
- Assert.assertTrue ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse("Invalid Javascript bindings",bindings.containsKey("bear"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsKey ("bear"));
-
- context.reset();
- bindings.put ("bear","grizzly");
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey("bear"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsKey ("bear"));
-
- context.set ("bear","koala");
- bindings.put("bear","grizzly");
- Assert.assertTrue ("Invalid SCXML context", context.has ("bear"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey("bear"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsKey ("bear"));
- }
-
- /**
- * Tests the <code>keySet</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testKeySet() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertFalse ("Invalid JSbindings", jsx.keySet().contains("bear"));
-
- context.set ("bear","koala");
- bindings.clear();
- Assert.assertTrue ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertTrue ("Invalid JSbindings", jsx.keySet().contains("bear"));
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertTrue ("Invalid JSbindings", jsx.keySet().contains("bear"));
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertTrue ("Invalid SCXML context", context.has ("cat"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey ("dog"));
- Assert.assertTrue ("Invalid JSbindings", jsx.keySet().contains("cat"));
- Assert.assertTrue ("Invalid JSbindings", jsx.keySet().contains("dog"));
- }
-
- /**
- * Tests the <code>size</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
-
- @Test
- public void testSize() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertEquals("Invalid JSbindings",0,jsx.size());
-
- context.set ("bear","koala");
- bindings.clear();
- Assert.assertTrue ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertEquals ("Invalid JSbindings",1,jsx.size());
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertEquals ("Invalid JSbindings",1,jsx.size());
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertTrue ("Invalid SCXML context", context.has ("bear"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertEquals ("Invalid JSbindings",1,jsx.size());
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertFalse ("Invalid SCXML context", context.has ("bear"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsKey ("bear"));
- Assert.assertTrue ("Invalid SCXML context", context.has ("cat"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsKey ("dog"));
- Assert.assertEquals ("Invalid JSbindings",2,jsx.size());
- }
-
- /**
- * Tests the <code>containsValue</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testContainsValue() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertFalse("Invalid SCXML context", context.getVars().containsValue("koala"));
- Assert.assertFalse("Invalid Javascript bindings",bindings.containsValue("koala"));
- Assert.assertFalse("Invalid JSbindings", jsx.containsValue ("koala"));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- Assert.assertTrue ("Invalid SCXML context", context.getVars().containsValue("koala"));
- Assert.assertFalse ("Invalid Javascript bindings",bindings.containsValue("koala"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsValue ("koala"));
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertFalse ("Invalid SCXML context", context.getVars().containsValue("grizzly"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsValue("grizzly"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsValue ("grizzly"));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertTrue ("Invalid SCXML context", context.getVars().containsValue("koala"));
- Assert.assertTrue ("Invalid Javascript bindings",bindings.containsValue("grizzly"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsValue ("koala"));
- Assert.assertTrue ("Invalid JSbindings", jsx.containsValue ("grizzly"));
- }
-
- /**
- * Tests the <code>entrySet</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testEntrySet() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertEquals("Invalid SCXML context", 0,context.getVars().entrySet().size());
- Assert.assertEquals("Invalid Javascript bindings",0,bindings.entrySet().size());
- Assert.assertEquals("Invalid JSbindings", 0,jsx.entrySet().size());
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().entrySet().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().entrySet().contains(KOALA));
- Assert.assertEquals ("Invalid Javascript bindings",0,bindings.entrySet().size());
- Assert.assertFalse ("Invalid Javascript bindings",bindings.entrySet().contains(KOALA));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.entrySet().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.entrySet().contains(KOALA));
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertEquals ("Invalid SCXML context", 0,context.getVars().entrySet().size());
- Assert.assertFalse ("Invalid SCXML context", context.getVars().entrySet().contains(GRIZZLY));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.entrySet().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.entrySet().contains(GRIZZLY));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.entrySet().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.entrySet().contains(GRIZZLY));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().entrySet().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().entrySet().contains(KOALA));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.entrySet().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.entrySet().contains(GRIZZLY));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.entrySet().size());
- Assert.assertFalse ("Invalid JSbindings", jsx.entrySet().contains(KOALA));
- Assert.assertTrue ("Invalid JSbindings", jsx.entrySet().contains(GRIZZLY));
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().entrySet().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().entrySet().contains(FELIX));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.entrySet().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.entrySet().contains(ROVER));
- Assert.assertEquals ("Invalid JSBindings", 2,jsx.entrySet().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.entrySet().contains(FELIX));
- Assert.assertTrue ("Invalid JSbindings", jsx.entrySet().contains(ROVER));
- }
-
- /**
- * Tests the <code>values</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testValues() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertEquals("Invalid SCXML context", 0,context.getVars().values().size());
- Assert.assertEquals("Invalid Javascript bindings",0,bindings.values().size());
- Assert.assertEquals("Invalid JSbindings", 0,jsx.values().size());
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().values().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().values().contains(KOALA.getValue()));
- Assert.assertEquals ("Invalid Javascript bindings",0,bindings.values().size());
- Assert.assertFalse ("Invalid Javascript bindings",bindings.values().contains(KOALA.getValue()));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.values().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.values().contains(KOALA.getValue()));
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertEquals ("Invalid SCXML context", 0,context.getVars().values().size());
- Assert.assertFalse ("Invalid SCXML context", context.getVars().values().contains(GRIZZLY.getValue()));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.values().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.values().contains(GRIZZLY.getValue()));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.values().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.values().contains(GRIZZLY.getValue()));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().values().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().values().contains(KOALA.getValue()));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.values().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.values().contains(GRIZZLY.getValue()));
- Assert.assertEquals ("Invalid JSBindings", 1,jsx.values().size());
- Assert.assertFalse ("Invalid JSbindings", jsx.values().contains(KOALA.getValue()));
- Assert.assertTrue ("Invalid JSbindings", jsx.values().contains(GRIZZLY.getValue()));
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertEquals ("Invalid SCXML context", 1,context.getVars().values().size());
- Assert.assertTrue ("Invalid SCXML context", context.getVars().values().contains(FELIX.getValue()));
- Assert.assertEquals ("Invalid Javascript bindings",1,bindings.values().size());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.values().contains(ROVER.getValue()));
- Assert.assertEquals ("Invalid JSBindings", 2,jsx.values().size());
- Assert.assertTrue ("Invalid JSbindings", jsx.values().contains(FELIX.getValue()));
- Assert.assertTrue ("Invalid JSbindings", jsx.values().contains(ROVER.getValue()));
- }
-
- /**
- * Tests the <code>isEmpty</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testIsEmpty() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertTrue("Invalid SCXML context", context.getVars().isEmpty());
- Assert.assertTrue("Invalid Javascript bindings",bindings.isEmpty());
- Assert.assertTrue("Invalid JSbindings", jsx.isEmpty());
-
- context.set ("bear","koala");
- bindings.clear();
- Assert.assertFalse ("Invalid SCXML context", context.getVars().isEmpty());
- Assert.assertTrue ("Invalid Javascript bindings",bindings.isEmpty());
- Assert.assertFalse ("Invalid JSbindings", jsx.isEmpty());
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertTrue ("Invalid SCXML context", context.getVars().isEmpty());
- Assert.assertFalse ("Invalid Javascript bindings",bindings.isEmpty());
- Assert.assertFalse ("Invalid JSbindings", jsx.isEmpty());
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertFalse ("Invalid SCXML context", context.getVars().isEmpty());
- Assert.assertFalse ("Invalid Javascript bindings",bindings.isEmpty());
- Assert.assertFalse ("Invalid JSbindings", jsx.isEmpty());
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertFalse ("Invalid SCXML context", context.getVars().isEmpty());
- Assert.assertFalse ("Invalid Javascript bindings",bindings.isEmpty());
- Assert.assertFalse ("Invalid JSbindings", jsx.isEmpty());
- }
-
- /**
- * Tests the <code>get</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testGet() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertNull("Invalid SCXML context", context.get ("bear"));
- Assert.assertNull("Invalid Javascript bindings",bindings.get("bear"));
- Assert.assertNull("Invalid JSbindings", jsx.get ("bear"));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- Assert.assertNotNull ("Invalid SCXML context", context.get ("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get ("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("bear"));
- Assert.assertEquals ("Invalid JSbindings","koala", jsx.get ("bear"));
-
- context.reset ();
- bindings.clear();
- bindings.put ("bear","grizzly");
- Assert.assertNull ("Invalid SCXML context", context.get ("bear"));
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("bear"));
- Assert.assertEquals ("Invalid JSbindings","grizzly", jsx.get ("bear"));
-
- context.reset ();
- bindings.clear();
- context.set ("bear","koala");
- bindings.put ("bear","grizzly");
- Assert.assertNotNull ("Invalid SCXML context", context.get ("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get ("bear"));
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("bear"));
- Assert.assertEquals ("Invalid JSbindings","grizzly", jsx.get ("bear"));
-
- context.reset ();
- bindings.clear();
- context.set ("cat","felix");
- bindings.put ("dog","rover");
- Assert.assertNotNull ("Invalid SCXML context", context.get ("cat"));
- Assert.assertEquals ("Invalid SCXML context","felix", context.get ("cat"));
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","rover",bindings.get("dog"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("cat"));
- Assert.assertEquals ("Invalid JSbindings","felix", jsx.get ("cat"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("dog"));
- Assert.assertEquals ("Invalid JSbindings","rover", jsx.get ("dog"));
- }
-
- /**
- * Tests the <code>put</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testPut() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- Assert.assertNull("Invalid SCXML context", context.get ("bear"));
- Assert.assertNull("Invalid Javascript bindings",bindings.get("bear"));
- Assert.assertNull("Invalid JSbindings", jsx.get ("bear"));
-
- jsx.put ("bear","koala");
- Assert.assertNotNull ("Invalid SCXML context", context.get ("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get("bear"));
- Assert.assertNotNull ("Invalid JSbindings", jsx.get ("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("bear"));
- }
-
- /**
- * Tests the <code>putAll</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testPutAll() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
- Map<String,Object> vars = new HashMap<String, Object>();
-
- vars.put("bear","grizzly");
- vars.put("cat","felix");
- vars.put("dog","rover");
-
- Assert.assertNull("Invalid SCXML context", context.get ("bear"));
- Assert.assertNull("Invalid SCXML context", context.get ("cat"));
- Assert.assertNull("Invalid SCXML context", context.get ("dog"));
-
- Assert.assertNull("Invalid Javascript bindings",bindings.get("bear"));
- Assert.assertNull("Invalid Javascript bindings",bindings.get("cat"));
- Assert.assertNull("Invalid Javascript bindings",bindings.get("dog"));
-
- Assert.assertNull("Invalid JSbindings", jsx.get ("bear"));
- Assert.assertNull("Invalid JSbindings", jsx.get ("cat"));
- Assert.assertNull("Invalid JSbindings", jsx.get ("dog"));
-
- context.set("bear","koala");
- jsx.putAll (vars);
-
- Assert.assertNotNull ("Invalid SCXML context", context.get ("bear"));
- Assert.assertNull ("Invalid SCXML context", context.get ("cat"));
- Assert.assertNull ("Invalid SCXML context", context.get ("dog"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get ("bear"));
- Assert.assertEquals ("Invalid SCXML context",1, context.getVars().size());
-
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNotNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","felix", bindings.get("cat"));
- Assert.assertEquals ("Invalid Javascript bindings","rover", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings",3, bindings.size());
- }
-
- /**
- * Tests the <code>remove</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testRemove() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- context.set ("bear","koala");
- bindings.put("bear","grizzly");
- bindings.put("cat", "felix");
- bindings.put("dog", "rover");
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context",1, context.getVars().size());
-
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","felix", bindings.get("cat"));
- Assert.assertEquals ("Invalid Javascript bindings","rover", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings",3, bindings.size());
-
- jsx.remove("cat");
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context",1, context.getVars().size());
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","rover", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings",2, bindings.size());
-
- jsx.remove("dog");
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context",1, context.getVars().size());
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings",1, bindings.size());
-
- jsx.remove("bear");
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals("Invalid SCXML context","koala",context.get("bear"));
- Assert.assertEquals("Invalid SCXML context",1, context.getVars().size());
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals("Invalid Javascript bindings",0,bindings.size());
-
- jsx.remove("bear");
-
- Assert.assertNull ("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals("Invalid SCXML context",0, context.getVars().size());
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals("Invalid Javascript bindings",0,bindings.size());
- }
-
- /**
- * Tests the <code>clear</code> method with items in the SCXML context as well as the
- * JavaScript Bindings.
- *
- */
- @Test
- public void testClear() {
- Context context = new JSContext ();
- Bindings bindings = new SimpleBindings();
- JSBindings jsx = new JSBindings (context,bindings);
-
- context.set ("bear","koala");
- bindings.put("bear","grizzly");
- bindings.put("cat", "felix");
- bindings.put("dog", "rover");
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context","koala",context.get("bear"));
- Assert.assertEquals ("Invalid SCXML context",1, context.getVars().size());
-
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNotNull("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings","grizzly",bindings.get("bear"));
- Assert.assertEquals ("Invalid Javascript bindings","felix", bindings.get("cat"));
- Assert.assertEquals ("Invalid Javascript bindings","rover", bindings.get("dog"));
- Assert.assertEquals ("Invalid Javascript bindings",3, bindings.size());
-
- jsx.clear();
-
- Assert.assertNotNull("Invalid SCXML context", context.get("bear"));
- Assert.assertEquals("Invalid SCXML context","koala",context.get("bear"));
- Assert.assertEquals("Invalid SCXML context",1, context.getVars().size());
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("bear"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("cat"));
- Assert.assertNull ("Invalid Javascript bindings", bindings.get("dog"));
- Assert.assertEquals("Invalid Javascript bindings",0,bindings.size());
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/test/java/org/apache/commons/scxml2/env/javascript/JavaScriptEngineTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/JavaScriptEngineTest.java b/src/test/java/org/apache/commons/scxml2/env/javascript/JavaScriptEngineTest.java
index c1bafaf..4ee8f0e 100644
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/JavaScriptEngineTest.java
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/JavaScriptEngineTest.java
@@ -16,79 +16,89 @@
*/
package org.apache.commons.scxml2.env.javascript;
-import static org.junit.Assert.assertEquals;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
+import java.util.UUID;
-import org.apache.commons.scxml2.Context;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.commons.scxml2.SCXMLSystemContext;
+import org.apache.commons.scxml2.StateConfiguration;
+import org.apache.commons.scxml2.Status;
+import org.apache.commons.scxml2.model.Final;
+import org.apache.commons.scxml2.system.EventVariable;
import org.junit.Before;
import org.junit.Test;
public class JavaScriptEngineTest {
- private ScriptEngine engine;
-
- private Context context;
+ private JSEvaluator evaluator;
+ private StateConfiguration stateConfiguration;
+ private JSContext _systemContext;
+ private JSContext context;
@Before
public void before() throws Exception {
- ScriptEngineManager factory = new ScriptEngineManager();
- engine = factory.getEngineByName("JavaScript");
- context = new JSContext();
+ evaluator = new JSEvaluator();
+ _systemContext = new JSContext();
+ SCXMLSystemContext systemContext = new SCXMLSystemContext(_systemContext);
+ _systemContext.set(SCXMLSystemContext.SESSIONID_KEY, UUID.randomUUID().toString());
+ _systemContext.set(SCXMLSystemContext.SCXML_NAME_KEY, "test");
+ stateConfiguration = new StateConfiguration();
+ systemContext.getPlatformVariables().put(SCXMLSystemContext.STATUS_KEY, new Status(stateConfiguration));
+ context = new JSContext(systemContext);
}
@Test
- public void testSimpleEvaluation() throws Exception {
- Object ret = engine.eval("1.0 + 2.0");
- assertEquals(3.0, ret);
+ public void testInitScxmlSystemContext() throws Exception {
+ assertEquals("test", evaluator.eval(context, "_name"));
}
@Test
- public void testBindingsInput() throws Exception {
- Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- bindings.put("x", 1.0);
- bindings.put("y", 2.0);
-
- Object ret = engine.eval("x + y;", bindings);
- assertEquals(3.0, ret);
+ public void testScxmlEvent() throws Exception {
+ assertTrue(evaluator.evalCond(context, "_event === undefined"));
+ EventVariable event = new EventVariable("myEvent", EventVariable.TYPE_INTERNAL, null, null, null, null,"myData");
+ _systemContext.setLocal(SCXMLSystemContext.EVENT_KEY, event);
+ assertFalse(evaluator.evalCond(context, "_event === undefined"));
+ assertTrue(evaluator.evalCond(context, "_event.name == 'myEvent'"));
+ assertTrue(evaluator.evalCond(context, "_event.type == 'internal'"));
+ assertTrue(evaluator.evalCond(context, "_event.data == 'myData'"));
+ assertTrue(evaluator.evalCond(context, "_event.origin === undefined"));
}
@Test
- public void testBindingsInput_WithJSBindings() throws Exception {
- Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- JSBindings jsBindings = new JSBindings(context, bindings);
- jsBindings.put("x", 1.0);
- jsBindings.put("y", 2.0);
-
- Object ret = engine.eval("x + y;", jsBindings);
- assertEquals(3.0, ret);
+ public void testScxmlInPredicate() throws Exception {
+ assertFalse(evaluator.evalCond(context, "In('foo')"));
+ Final foo = new Final();
+ foo.setId("foo");
+ stateConfiguration.enterState(foo);
+ assertTrue(evaluator.evalCond(context, "In('foo')"));
}
@Test
- public void testBindingsGlobal() throws Exception {
- Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- bindings.put("x", 1.0);
- bindings.put("y", 2.0);
- bindings.put("z", 0.0);
-
- engine.eval("z = x + y;", bindings);
- assertEquals("z variable is expected to set to 3.0 in global, but it was " + bindings.get("z") + ".",
- 3.0, bindings.get("z"));
+ public void testCopyJavscriptGlobalsToScxmlContext() throws Exception {
+ assertFalse(context.has("x"));
+ evaluator.eval(context, ("x=3"));
+ assertEquals(3, context.get("x"));
}
@Test
- public void testBindingsGlobal_WithJSBindings() throws Exception {
- Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- JSBindings jsBindings = new JSBindings(context, bindings);
- jsBindings.put("x", 1.0);
- jsBindings.put("y", 2.0);
- jsBindings.put("z", 0.0);
+ public void testSharedJavscriptGlobalsRetainedAcrossInvocation() throws Exception {
+ assertFalse(context.has("x"));
+ evaluator.eval(context, ("x=3"));
+ context.getVars().remove("x");
+ assertFalse(context.has("x"));
+ assertTrue(evaluator.evalCond(context, "x===3"));
+ }
- engine.eval("z = x + y;", jsBindings);
- assertEquals("z variable is expected to set to 3.0 in global, but it was " + jsBindings.get("z") + ".",
- 3.0, jsBindings.get("z"));
+ @Test
+ public void testJavscriptGlobalsNotRetainedAcrossEvaluatorInstances() throws Exception {
+ assertFalse(context.has("x"));
+ evaluator.eval(context, ("x=3"));
+ assertEquals(3, context.get("x"));
+ context.getVars().remove("x");
+ assertFalse(context.has("x"));
+ evaluator = new JSEvaluator();
+ assertTrue(evaluator.evalCond(context, "typeof x=='undefined'"));
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/1b91a77c/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
index f3657a6..90ee864 100644
--- a/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
+++ b/src/test/java/org/apache/commons/scxml2/w3c/tests.xml
@@ -89,15 +89,15 @@
<test id="325" mandatory="true" manual="false" enabled="false" ecma="fail"/>
<test id="326" mandatory="true" manual="false" enabled="false" ecma="fail"/>
<test id="329" mandatory="true" manual="false" enabled="true" ecma="pass"/>
- <test id="330" mandatory="true" manual="false" enabled="false" ecma="fail"/>
+ <test id="330" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="331" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="332" mandatory="true" manual="false" enabled="false" ecma="fail"/>
- <test id="333" mandatory="true" manual="false" enabled="false" ecma="fail"/>
- <test id="335" mandatory="true" manual="false" enabled="false" ecma="fail"/>
+ <test id="333" mandatory="true" manual="false" enabled="true" ecma="pass"/>
+ <test id="335" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="336" mandatory="true" manual="false" enabled="true" ecma="pass"/>
- <test id="337" mandatory="true" manual="false" enabled="false" ecma="fail"/>
+ <test id="337" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="338" mandatory="true" manual="false" enabled="false" ecma="" >Fails to complete</test>
- <test id="339" mandatory="true" manual="false" enabled="false" ecma="fail"/>
+ <test id="339" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="342" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="346" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="172" mandatory="true" manual="false" enabled="true" ecma="pass"/>
@@ -118,7 +118,7 @@
<test id="201" mandatory="false" manual="false" enabled="false" ecma="fail"/>
<test id="205" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="521" mandatory="true" manual="false" enabled="false" ecma="fail"/>
- <test id="553" mandatory="true" manual="false" enabled="false" ecma="pass"/>
+ <test id="553" mandatory="true" manual="false" enabled="true" ecma="pass"/>
<test id="207" mandatory="true" manual="false" enabled="false" ecma="" >Fails to complete</test>
<test id="208" mandatory="true" manual="false" enabled="false" ecma="fail"/>
<test id="210" mandatory="true" manual="false" enabled="false" ecma="fail"/>
@@ -155,7 +155,7 @@
<test id="278" mandatory="false" manual="false" enabled="false" ecma="fail"/>
<test id="444" mandatory="false" manual="false" enabled="true" ecma="pass"/>
<test id="445" mandatory="false" manual="false" enabled="true" ecma="pass"/>
- <test id="448" mandatory="false" manual="false" enabled="false" ecma="fail"/>
+ <test id="448" mandatory="false" manual="false" enabled="true" ecma="pass"/>
<test id="449" mandatory="false" manual="false" enabled="true" ecma="pass"/>
<test id="451" mandatory="false" manual="false" enabled="true" ecma="pass"/>
<test id="452" mandatory="false" manual="false" enabled="true" ecma="pass"/>