nashorn 中的可选链接 (?.)

Optional chaining (?.) in nashorn

我在我的项目中使用nashorn。我想从 json 中获取 属性,但 属性 可能没有价值。

在javascript中,使用可选链接并设置一个值,如果属性为空;但在 nashorn 中,当我使用 (?.) 时,出现此错误:

import org.springframework.stereotype.Service
import javax.script.ScriptEngineManager
import javax.script.Bindings

@Service
class SampleService {

    class Person(
            val firstName: String,
            val lastName: String,
            val child: Child?
    )

    class Child(
            val name: String,
            val age: Int
    )

    fun runScript() {
        val engine = ScriptEngineManager().getEngineByName("nashorn")
        val bindings: Bindings = engine.createBindings()
        val person = Person("John", "Smite", null)
        bindings["person"] = person
        try {
            val script = """
               var childAge = person.child?.age ?? 0;
               childAge; //return as result.
            """.trimIndent()
            val scriptResult: Any = engine.eval(script, bindings)
        } catch (e: Exception) {
            throw e
        }

    }
}

我收到这个错误:

javax.script.ScriptException: <eval>:1:28 Expected an operand but found .
var childAge = person.child?.age ?? 0;
^ in <eval> at line number 1 at column number 28

我检查了这个link,但我无法解决问题: Optional chaining (?.)

我该如何解决这个错误?

Nashorn 目前的策略是遵循 ECMAScript 规范。当我们发布 JDK 8 时,我们将与 ECMAScript 5.1 保持一致。link

作为 JEP 335 的一部分,Nashorn 引擎已在 JDK 11 中弃用,并计划作为 JEP 372 的一部分从未来的 JDK 版本中删除。

GraalVM JavaScript can step in as a replacement for code previously executed on the Nashorn engine. It provides all the features previously provided by Nashorn, with many being available by default, some behind flags, some requiring minor modifications to your source code.link

可选链接非常新,ECMAScript 5.1 不支持此功能。

我从 nashorn 迁移到 GraalVM JavaScript 并更改了代码如下:

import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine
import org.graalvm.polyglot.Context
import org.graalvm.polyglot.HostAccess
import org.springframework.stereotype.Service
import javax.script.ScriptEngine


@Service
class SampleService {

    data class Person(
            val firstName: String,
            val lastName: String,
            val child: Child?
    )

    data class Child(
            val name: String,
            val age: Int
    )

    fun runScript() {

        val person = Person("John", "Smite", null)

        val engine: ScriptEngine = GraalJSScriptEngine.create(null,
                Context.newBuilder("js")
                        .allowHostAccess(HostAccess.ALL)
                        .allowExperimentalOptions(true)
                        .option("js.ecmascript-version", "2020")
                        .option("js.nashorn-compat", "true"))
        engine.put("person", person)
        try {
            val script = """
                print(person.child?.name);
                //print undefined
                print(person.child?.name ?? 'not exist');
                //print not exist
            """.trimIndent()
            engine.eval(script)
        } catch (e: Exception) {
            throw e
        }
    }
}