mobile-dev-inc/maestro

Deprecate Rhino JavaScript engine

bartekpacia opened this issue · 5 comments

TL;DR

We will deprecate Rhino JavaScript engine, thus making GraalJS the only choice.

To prepare for this, explicitly set jsEngine: graaljs in front-matter of every flow that uses JavaScript:

appId: com.example.app
jsEngine: graaljs # <-- Opt-in to use GraalJS engine
---
- launchApp
- runScript: ./myScript.js

Plan

Let's do it in phases, to spare our users sudden breakages.

Phase 1 - communicate

  • Communicate to community our intent to deprecate RhinoJS
    • In our public Slack workspace, in the #announcements channel
    • In v1.39.0 release Medium post
    • In v1.39.0 CHANGELOG.md
    • In our JavaScript docs

Phase 2 - soft warning

  • Add warning (in both CLI and Maestro Cloud) if GraalJS is not used to execute a flow (i.e. jsEngine: graaljs is not set, or MAESTRO_USE_GRAALJS env var is not set).
  • Ping the community once again about our intent to deprecate GraalJS

Phase 3 - change default

  • Change default JS engine to GraalJS (in both CLI and Maestro Cloud)
  • Display warning if RhinoJS is used (with jsEngine: rhinojs)

Phase 4 - remove RhinoJS

  • Remove RhinoJS completely from Maestro codebase
  • Display warning if jsEngine or MAESTRO_USE_GRAALJS are set - say that "these config options don't have any effect anymore"

Notes

  • GraalJS was implemented in PR #1147
  • As we move ahead with phases, we will listen for user feedback and help them migrate to GraalJS, by fixing possible bugs in Maestro when GraalJS is used and improving docs.

I switched all of my tests from Rhino to GraalJS.
No issues encountered, no changes needed. 👍

I have installed Maestro 1.39.0 on macOS 15.0.1 (24A348) using Homebrew. When I run any script using the GraalJS engine, I encounter the following exception immediately:

Exception in thread "main" java.lang.NoSuchMethodError: 'void sun.misc.Unsafe.ensureClassInitialized(java.lang.Class)'
	at com.oracle.truffle.api.library.LibraryFactory.ensureLibraryInitialized(LibraryFactory.java:384)
	at com.oracle.truffle.api.library.LibraryFactory.getUncached(LibraryFactory.java:364)
	at com.oracle.truffle.api.library.LibraryFactory.<init>(LibraryFactory.java:210)
	at com.oracle.truffle.api.interop.InteropLibraryGen.<init>(InteropLibraryGen.java:170)
	at com.oracle.truffle.api.interop.InteropLibraryGen.<clinit>(InteropLibraryGen.java:161)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:578)
	at java.base/java.lang.Class.forName(Class.java:557)
	at com.oracle.truffle.api.library.LibraryFactory.loadGeneratedClass(LibraryFactory.java:777)
	at com.oracle.truffle.api.library.LibraryFactory.resolveImpl(LibraryFactory.java:740)
	at com.oracle.truffle.api.library.LibraryFactory.resolve(LibraryFactory.java:733)
	at com.oracle.truffle.api.interop.InteropLibrary.<clinit>(InteropLibrary.java:2843)
	at com.oracle.truffle.polyglot.PolyglotValueDispatch.<clinit>(PolyglotValueDispatch.java:155)
	at com.oracle.truffle.polyglot.PolyglotImpl.initialize(PolyglotImpl.java:163)
	at org.graalvm.polyglot.impl.AbstractPolyglotImpl.setConstructors(AbstractPolyglotImpl.java:266)
	at org.graalvm.polyglot.Engine$1.loadAndValidateProviders(Engine.java:917)
	at org.graalvm.polyglot.Engine$1.run(Engine.java:890)
	at org.graalvm.polyglot.Engine$1.run(Engine.java:864)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
	at org.graalvm.polyglot.Engine.initEngineImpl(Engine.java:864)
	at org.graalvm.polyglot.Engine.access$000(Engine.java:110)
	at org.graalvm.polyglot.Engine$ImplHolder.<clinit>(Engine.java:136)
	at org.graalvm.polyglot.Engine.getImpl(Engine.java:360)
	at org.graalvm.polyglot.Source.getImpl(Source.java:140)
	at org.graalvm.polyglot.Source$Builder.build(Source.java:920)
	at maestro.js.GraalJsEngine.evaluateScript(GraalJsEngine.kt:69)
	at maestro.js.GraalJsEngine.evaluateScript(GraalJsEngine.kt:22)
	at maestro.orchestra.Orchestra.runScriptCommand(Orchestra.kt:418)
	at maestro.orchestra.Orchestra.executeCommand(Orchestra.kt:288)
	at maestro.orchestra.Orchestra.executeCommands(Orchestra.kt:193)
	at maestro.orchestra.Orchestra.runFlow(Orchestra.kt:127)
	at maestro.cli.runner.MaestroCommandRunner.runCommands(MaestroCommandRunner.kt:177)
	at maestro.cli.runner.TestRunner$runSingle$result$1.invoke(TestRunner.kt:62)
	at maestro.cli.runner.TestRunner$runSingle$result$1.invoke(TestRunner.kt:53)
	at maestro.cli.runner.TestRunner.runCatching(TestRunner.kt:160)
	at maestro.cli.runner.TestRunner.runSingle(TestRunner.kt:53)
	at maestro.cli.command.TestCommand.runSingleFlow(TestCommand.kt:352)
	at maestro.cli.command.TestCommand.access$runSingleFlow(TestCommand.kt:63)
	at maestro.cli.command.TestCommand$runShardSuite$2.invoke(TestCommand.kt:326)
	at maestro.cli.command.TestCommand$runShardSuite$2.invoke(TestCommand.kt:297)
	at maestro.cli.session.MaestroSessionManager.newSession(MaestroSessionManager.kt:102)
	at maestro.cli.session.MaestroSessionManager.newSession$default(MaestroSessionManager.kt:52)
	at maestro.cli.command.TestCommand.runShardSuite(TestCommand.kt:297)
	at maestro.cli.command.TestCommand.access$runShardSuite(TestCommand.kt:63)
	at maestro.cli.command.TestCommand$handleSessions$1$results$1$1.invokeSuspend(TestCommand.kt:265)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)

It's possible that the version of GraalJS used by Maestro is incompatible with OpenJDK 23, which Homebrew installs automatically as a dependency. I was able to work around the issue by manually installing OpenJDK 21 on my Mac.

The exception was also reported here: oracle/graaljs#825.

@bartekpacia Should I create a separate issue for this problem?

That's always a good idea:) and link to this one