用实际文件名替换Java Rhino(JSR223)中的<Unknown Source>

8
在我的代码中,所有的脚本都包含在.js文件中。每当一个脚本出现错误时,我会得到以下错误信息:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "nonexistant" is not defined. (<Unknown source>#5) in <Unknown source> at line number 5
让我困扰的是<Unknown Source>。多个文件在一个ScriptContext中,很难追踪错误。而且它看起来很糟糕。
有没有办法将<Unknown Source>替换为实际的文件名?我看到的所有方法都不支持传递File对象,所以我真的很困惑。
4个回答

12
使用ScriptEngine.FILENAME常量: scriptEngine.put(ScriptEngine.FILENAME, scriptFile.toString());

6

虽然还没有明确提出这个问题,但我想为将来偶然看到这个主题的任何人提供帮助:随着Java 8发布并将其底层JavaScript引擎从Rhino更换为Nashorn,这将发生变化。在Nashorn下,文件名应用于ScriptContext而不是ScriptEngine本身:

ScriptContext context = new SimpleScriptContext();
context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
try
{
    engine.eval(script, context);
}
catch (ScriptException e)
{
    /* e.getFileName() will return "test.js" */
}

如果您尝试使用ScriptEngine.put()来应用文件名(就像在Rhino下一样),那么什么也不会发生,并且您的异常将返回"<eval>"作为文件名。我想在未来几个月中,会有一些人遇到这个问题,所以我想提供一下。这似乎没有在任何地方记录下来。我必须深入研究Nashorn源代码才能弄清楚。

这是一个与编程��关的内容。Java 8已经发布很久了,Java 9也即将到来。 :) - Per Lundberg

3

通过ScriptContext设置脚本引擎的文件名是Java 8(Nashorn)的方法,由mattj65816发现,对Rhino引擎也适用。因此,我建议仅使用此方法。

context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);

由于这段代码适用于常见的JavaScript引擎,因此您甚至不需要创建自己的上下文,只需将属性设置为引擎的默认上下文即可:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
if (engine != null) {
    ScriptContext ctx = engine.getContext();
    ctx.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
    ...
}

0

太完美了!

    ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
    // javax.script.filename
    engine.put(ScriptEngine.FILENAME, "test1.js");
    try {
        engine.eval("function throwError1(){throw new Error('test, haha')}");
    } catch (ScriptException e) {
    }       

    engine.put(ScriptEngine.FILENAME, "test2.js");
    try {
        engine.eval("function throwError2(){throw new Error('test2, haha')}");
    } catch (ScriptException e) {
    }
    try {
        engine.eval("throwError1()");
    } catch (ScriptException e) {
        System.out.println(e.getMessage());
    }
    try {
        engine.eval("throwError2()");
    } catch (ScriptException e) {
        System.out.println(e.getMessage());
    }

输出:

Error: test, haha in test1.js at line number 1
Error: test2, haha in test2.js at line number 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接