File: JavaScriptEvaluator.java

package info (click to toggle)
imagej 1.52j-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,604 kB
  • sloc: java: 120,017; sh: 279; xml: 161; makefile: 6
file content (89 lines) | stat: -rw-r--r-- 2,509 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package ij.plugin;
import ij.*;
import ij.plugin.frame.Editor;
import javax.script.*;

/** Implements the text editor's Macros/Run command, and the
    IJ.runMacroFile() method, when the file name ends with ".js". */
public class JavaScriptEvaluator implements PlugIn, Runnable  {
	private Thread thread;
	private String script;
	private Object result;
	private String error;
	private boolean evaluating;
	ScriptEngine engine;

	// run script in separate thread
	public void run(String script) {
		if (script.equals(""))
			return;
		this.script = script;
		thread = new Thread(this, "JavaScript"); 
		thread.setPriority(Math.max(thread.getPriority()-2, Thread.MIN_PRIORITY));
		thread.start();
	}

	// Run script in current thread
	public String run(String script, String arg) {
		this.script = script;
		run();
		return null;
	}

	// Evaluates 'script' and returns any error messages as a String. 
	public String eval(String script) {
		this.script = script;
		evaluating = true;
		run();
		if (error!=null)
			return error;
		else
			return result!=null?""+result:"";
	}

	public void run() {
		result = null;
		error = null;
		Thread.currentThread().setContextClassLoader(IJ.getClassLoader());
		if (IJ.isJava19())
			System.setProperty("nashorn.args", "--language=es6"); // Use ECMAScript 6 on Java 9
		try {
			if (engine==null) {
				ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
				engine = scriptEngineManager.getEngineByName("ECMAScript");
				if (engine == null) {
					IJ.error("Could not find JavaScript engine");
					return;
				}
				if (!IJ.isJava18()) {
					engine.eval("function load(path) {\n"
						+ "  importClass(Packages.sun.org.mozilla.javascript.internal.Context);\n"
						+ "  importClass(Packages.java.io.FileReader);\n"
						+ "  var cx = Context.getCurrentContext();\n"
						+ "  cx.evaluateReader(this, new FileReader(path), path, 1, null);\n"
						+ "}");
				}
			}
			result = engine.eval(script);
		} catch(Throwable e) {
			String msg = e.getMessage();
			if (msg==null)
				msg = "";
			if (msg.startsWith("sun.org.mozilla.javascript.internal.EcmaError: "))
				msg = msg.substring(47, msg.length());
			if (msg.startsWith("sun.org.mozilla.javascript.internal.EvaluatorException"))
				msg = "Error"+msg.substring(54, msg.length());
			if (msg.length()>0 && !msg.contains("Macro canceled")) {
				if (evaluating)
					error = msg;
				else
					IJ.log(msg);
			}
		}
	}
	
	public String toString() {
		return result!=null?""+result:"";
	}

}