英文:
Nashorn (es6) corrupted function scope
问题
我目前正在调查Nashorn js脚本引擎中的以下问题,并且我会感谢您的意见。以下是代码段(使用Kotlin编写):
fun main() {
val brokenScript = """
function fn() {
const object1 = { "name": "Pepa" };
print(object1.name);
const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'name');
print(descriptor1.configurable);
print(eval("3+1"));
}
fn();
""".trimIndent()
NashornScriptEngineFactory()
.getScriptEngine("--no-deprecation-warning", "--language=es6", "--log=compiler:finest,fields,recompile:fine")
.let { (it as Compilable).compile(brokenScript) }
.also { script -> script.eval() }
}
错误信息:
Exception in thread "main" javax.script.ScriptException: ReferenceError: "descriptor1" is not defined in <eval> at line number 8
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:477)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:461)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:517)
at java.scripting/javax.script.CompiledScript.eval(CompiledScript.java:103)
at MainKt.main(Main.kt:19)
at MainKt.main(Main.kt)
Caused by: <eval>:8 ReferenceError: "descriptor1" is not defined
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:278)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.AccessorProperty.checkUndeclared(AccessorProperty.java:571)
...
观察结果:
- 问题受到eval函数的影响 - 从脚本中省略它有帮助 - 还需要嵌套在函数中 - 在顶层工作正常
- 问题受到Object.getOwnPropertyDescriptor函数的影响 - 从脚本中省略它有帮助
- 问题受到作用域的影响 - 将变量声明从具有作用域的(const/let)更改为无作用域的var有帮助
- 输出日志包含
caught RewriteException [pp=3, type=object, value='Pepa')]
当前假设:
Object.getOwnPropertyDescriptor函数引发UnwarrantedOptimismException,强制函数重新编译。
重新编译脚本的作用域受损。通常,作用域是通过eval函数的使用来操作的,因此在运行时重新编译期间可能会不正确地解析这个问题。
访问作用域变量失败。
我希望的结果是什么?(按优先顺序排列)
- 它可以像在节点中执行时一样工作 - 显然
- 在不关闭es6功能的情况下在编译时识别问题
- 禁用eval函数可以防止问题 - 我尝试过从Bindings对象中删除eval,但是脚本在编译阶段就已损坏,并且稍后将修改的Bindings传递给
script.eval(bindings)
- 因此脚本在到达eval行之前仍会失败 - (实际上,这是我试图避免的)通过关闭es6功能来绕过问题(删除**--language=es6** - 这会导致脚本在编译时由于使用作用域变量(const/let)而失败)
(我知道Nashorn已经被弃用,将被移除。)
英文:
I am currently investigating following issue in Nashorn js scripting engine and I'd appreciate your input.
Following code snippet fails execution (code in Kotlin):
fun main() {
   val brokenScript = """
       function fn() {
           const object1 = { "name": "Pepa" };
           print(object1.name);
           const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'name');
           print(descriptor1.configurable);
           print(eval("3+1"));
       }
       fn();
   """.trimIndent()
   NashornScriptEngineFactory()
           .getScriptEngine("--no-deprecation-warning", "--language=es6", "--log=compiler:finest,fields,recompile:fine")
           .let { (it as Compilable).compile(brokenScript) }
           .also { script -> script.eval() }
}
Error:
Exception in thread "main" javax.script.ScriptException: ReferenceError: "descriptor1" is not defined in <eval> at line number 8
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:477)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:461)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:517)
at java.scripting/javax.script.CompiledScript.eval(CompiledScript.java:103)
at MainKt.main(Main.kt:19)
at MainKt.main(Main.kt)
Caused by: <eval>:8 ReferenceError: "descriptor1" is not defined
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:278)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.AccessorProperty.checkUndeclared(AccessorProperty.java:571)
...
Observations:
- issue is influenced by eval function - ommiting it from script helps - also need to be nested in function - works fine at top level
- issue is influenced by Object.getOwnPropertyDescriptor function - ommiting it from script helps
- issue is influenced by scoping - changing variable declaration from scoped (const/let) to unscoped var helps
- output log contains
caught RewriteException [pp=3, type=object, value='Pepa')]
Current hypothesis:
Object.getOwnPropertyDescriptor function raises UnwarrantedOptimismException that forces the function to recompile.
Scope of recompiled script is corrupted. Usually the scope is manipulated by eval function usage so it can declare variables - maybe this is resolved incorrectly during the runtime recompilation.
Accessing scoped variables fails.
What outcome I hope for?(in order of preference)
- it works just as when executed in node - obviously
- issue is identified at compile time without turning off es6 features
- disabling eval function prevents the issue - I tried this by removing eval from Bindings object but script is corrupted at compilation phase and modified Bindings are passed later to
script.eval(bindings)
- so the script still fails before reaching eval line - (this is actually what I try to avoid) bypassing issue by turning off es6 features (removing --language=es6 - this forces the script to fail at compile time due to usage of scoped variables (const/let)
(I am aware that nashorn is deprecated and will be removed.)
答案1
得分: 0
我们在Nashorn和JDK 9+中也遇到了类似的问题。似乎是“乐观类型”导致了这个问题。尝试禁用Nashorn的乐观类型。
.getScriptEngine("--no-deprecation-warning", "--language=es6", "--log=compiler:finest,fields,recompile:fine", "--optimistic-types=false")
参考:https://openjdk.java.net/jeps/196
英文:
We also had similar problem with Nashorn and JDK 9+. It seems like optimistic types
causes this problem. Try disabling optimistic types for Nashorn
.getScriptEngine("--no-deprecation-warning", "--language=es6", "--log=compiler:finest,fields,recompile:fine", "--optimistic-types=false")
专注分享java语言的经验与见解,让所有开发者获益!
评论