Nashorn(es6)损坏的函数作用域

huangapple 未分类评论48阅读模式
英文:

Nashorn (es6) corrupted function scope

问题

我目前正在调查Nashorn js脚本引擎中的以下问题,并且我会感谢您的意见。以下是代码段(使用Kotlin编写):

  1. fun main() {
  2. val brokenScript = """
  3. function fn() {
  4. const object1 = { "name": "Pepa" };
  5. print(object1.name);
  6. const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'name');
  7. print(descriptor1.configurable);
  8. print(eval("3+1"));
  9. }
  10. fn();
  11. """.trimIndent()
  12. NashornScriptEngineFactory()
  13. .getScriptEngine("--no-deprecation-warning", "--language=es6", "--log=compiler:finest,fields,recompile:fine")
  14. .let { (it as Compilable).compile(brokenScript) }
  15. .also { script -> script.eval() }
  16. }

错误信息:

  1. Exception in thread "main" javax.script.ScriptException: ReferenceError: "descriptor1" is not defined in <eval> at line number 8
  2. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:477)
  3. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:461)
  4. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:517)
  5. at java.scripting/javax.script.CompiledScript.eval(CompiledScript.java:103)
  6. at MainKt.main(Main.kt:19)
  7. at MainKt.main(Main.kt)
  8. Caused by: <eval>:8 ReferenceError: "descriptor1" is not defined
  9. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
  10. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319)
  11. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)
  12. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:278)
  13. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.AccessorProperty.checkUndeclared(AccessorProperty.java:571)
  14. ...

观察结果:

  • 问题受到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):

  1. fun main() {
  2. &#160; &#160;val brokenScript = &quot;&quot;&quot;
  3. &#160; &#160; &#160; &#160;function fn() {
  4. &#160; &#160; &#160; &#160; &#160; &#160;const object1 = { &quot;name&quot;: &quot;Pepa&quot; };
  5. &#160; &#160; &#160; &#160; &#160; &#160;print(object1.name);
  6. &#160; &#160; &#160; &#160; &#160; &#160;const descriptor1 = Object.getOwnPropertyDescriptor(object1, &#39;name&#39;);
  7. &#160; &#160; &#160; &#160; &#160; &#160;print(descriptor1.configurable);
  8. &#160; &#160; &#160; &#160; &#160; &#160;print(eval(&quot;3+1&quot;));
  9. &#160; &#160; &#160; &#160;}
  10. &#160; &#160; &#160; &#160;fn();
  11. &#160; &#160;&quot;&quot;&quot;.trimIndent()
  12. &#160; &#160;NashornScriptEngineFactory()
  13. &#160; &#160; &#160; &#160; &#160; &#160;.getScriptEngine(&quot;--no-deprecation-warning&quot;, &quot;--language=es6&quot;, &quot;--log=compiler:finest,fields,recompile:fine&quot;)
  14. &#160; &#160; &#160; &#160; &#160; &#160;.let { (it as Compilable).compile(brokenScript) }
  15. &#160; &#160; &#160; &#160; &#160; &#160;.also { script -&gt; script.eval() }
  16. }

Error:

  1. Exception in thread &quot;main&quot; javax.script.ScriptException: ReferenceError: &quot;descriptor1&quot; is not defined in &lt;eval&gt; at line number 8
  2. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:477)
  3. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:461)
  4. at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine$3.eval(NashornScriptEngine.java:517)
  5. at java.scripting/javax.script.CompiledScript.eval(CompiledScript.java:103)
  6. at MainKt.main(Main.kt:19)
  7. at MainKt.main(Main.kt)
  8. Caused by: &lt;eval&gt;:8 ReferenceError: &quot;descriptor1&quot; is not defined
  9. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
  10. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319)
  11. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291)
  12. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:278)
  13. at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.AccessorProperty.checkUndeclared(AccessorProperty.java:571)
  14. ...

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=&#39;Pepa&#39;)]

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的乐观类型。

  1. .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

  1. .getScriptEngine(&quot;--no-deprecation-warning&quot;, &quot;--language=es6&quot;, &quot;--log=compiler:finest,fields,recompile:fine&quot;, &quot;--optimistic-types=false&quot;)

Ref: https://openjdk.java.net/jeps/196

huangapple
  • 本文由 发表于 2020年5月5日 20:32:08
  • 转载请务必保留本文链接:https://java.coder-hub.com/61613216.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定