Skip to content

Commit

Permalink
java-json-tools#96: add support for GraalJS script engine on RegExp c…
Browse files Browse the repository at this point in the history
…hecks
  • Loading branch information
sdoeringNew committed Nov 16, 2020
1 parent 9af226f commit 9aac928
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@
* the full story. And if you don't yet have Jeffrey Friedl's "Mastering regular
* expressions", just <a href="http://regex.info">buy it</a> :p</p>
*
* <p>As script engine is used either Nashorn or Rhino as its fallback.
* Nashorn is only available on Java 8 up to 14.</p>
* <p>As script engine is used either GraalJS, Nashorn or Rhino as their
* fallback. Nashorn is only available on Java 8 up to 14.</p>
*
* <p>Rhino is the fallback as it is tremendously slower.</p>
* <p>GraalJS is the first choice as it supports more RegExp features, e.g.
* lookbehind assertions, than both alternatives.</p>
*
* <p>Rhino is the fallback as it is tremendously slower than Nashorn.</p>
*/
@ThreadSafe
public final class RegexECMA262Helper
Expand Down Expand Up @@ -89,10 +92,15 @@ private RegexECMA262Helper()

private static RegexScript determineRegexScript()
{
try {
return new GraalJsScript();
} catch(final ScriptException e) {
// most probably GraalJS is simply not available
}
try {
return new NashornScript();
} catch(final ScriptException e) {
// either Nashorn is not available or the JavaScript can't be parsed
// most probably Nashorn is simply not available
}
return new RhinoScript();
}
Expand Down Expand Up @@ -134,26 +142,25 @@ private interface RegexScript
boolean regMatch(String regex, String input);
}

private static class NashornScript implements RegexScript
private static abstract class ScriptEngineScript implements RegexScript
{
/**
* Script engine
*/
private final Invocable scriptEngine;

private NashornScript() throws ScriptException
private ScriptEngineScript(final String engineName) throws ScriptException
{
final ScriptEngine engine = new ScriptEngineManager()
.getEngineByName("nashorn");
if (engine == null) {
throw new ScriptException("ScriptEngine 'nashorn' not found.");
.getEngineByName(engineName);
if(engine == null) {
throw new ScriptException("ScriptEngine '" + engineName + "' not found.");
}
engine.eval(jsAsString);
this.scriptEngine = (Invocable) engine;
}

private boolean invokeScriptEngine(final String function,
final Object... values)
boolean invoke(final String function, final Object... values)
{
try {
return (Boolean) scriptEngine.invokeFunction(function,
Expand All @@ -178,6 +185,37 @@ public boolean regMatch(final String regex, final String input)
{
return invokeScriptEngine(REG_MATCH_FUNCTION_NAME, regex, input);
}

abstract boolean invokeScriptEngine(final String function, final Object... values);
}

private static class GraalJsScript extends ScriptEngineScript
{
private GraalJsScript() throws ScriptException
{
super("graal.js");
}

// GraalJS works single-threaded. The synchronized ensures this.
@Override
synchronized boolean invokeScriptEngine(final String function,
final Object... values) {
return invoke(function, values);
}
}

private static class NashornScript extends ScriptEngineScript
{
private NashornScript() throws ScriptException
{
super("nashorn");
}

@Override
boolean invokeScriptEngine(final String function,
final Object... values) {
return invoke(function, values);
}
}

private static class RhinoScript implements RegexScript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public Iterator<Object[]> ecma262regexes()
{
return ImmutableList.of(
new Object[] { "[^]", true },
new Object[] { "(?<=foo)bar", false },
new Object[] { "(?<=foobar", false },
new Object[] { "", true },
new Object[] { "[a-z]+(?!foo)(?=bar)", true }
).iterator();
Expand Down

0 comments on commit 9aac928

Please sign in to comment.