Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Nashorn JS Engine used for Lambdas #571

Closed
robotdan opened this issue Apr 21, 2020 · 12 comments
Closed

Replace Nashorn JS Engine used for Lambdas #571

robotdan opened this issue Apr 21, 2020 · 12 comments
Milestone

Comments

@robotdan
Copy link
Member

robotdan commented Apr 21, 2020

Replace Nashorn JS Engine used for Lambdas

Problem

Nashorn sucks and is old and deprecated. Now that we are on JDK14, it is likely going to be removed shortly.

Solution

Use v8, or something else that is more full featured.
https://v8.dev/
https://github.com/eclipsesource/J2V8

Alternatives/workarounds

N/A

Related

Additional context

Add any other context or screenshots about the feature request here.

How to vote

Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.

@mooreds
Copy link
Collaborator

mooreds commented Apr 23, 2020

A former company used GraalVM: https://www.transposit.com/blog/2019.01.02-graalvm-holy/

@robotdan
Copy link
Member Author

robotdan commented Apr 23, 2020

We have looked at that, and it is an option. I think that is a whole VM though. It is GPL, but does also have a Classpath exception.

https://www.graalvm.org/docs/faq/

I may be mistaken, but I think for us to go this path, we'd use this whole VM as our runtime instead of the standard OpenJDK.

The upside of using v8 is that it is v8. :-)

According to GraalVM - it is ECMA Script 2020 compliant and perhaps even based upon Node.js - so maybe equivalent there.

GraalVM JavaScript Compatibility

GraalVM is ECMAScript 2019 compliant and fully compatible with a diverse range of active Node.js (npm) modules. It will also be compliant to ECMAScript 2020 once this updated specification is published (draft spec). More than 100,000 npm packages are regularly tested and are compatible with GraalVM, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. The latest release of GraalVM is based on Node.js version 12.14.0.

https://www.graalvm.org/docs/reference-manual/languages/js/#interoperability

@tyduptyler13
Copy link

Pros of graal:

  • Polyglot (lambdas could be written in pretty much any language and still run in the JVM)
  • AOT compiling for some of our code so in theory some improved performance (I already investigated graal native and we use WAY too much dynamic reflection for this to ever be possible, but the standard vm still does some AOT compilation so its not a huge deal, we just won't have standalone executables)

Cons of graal:

  • Only supports java 8 and java 11
  • You have to use their JVM because its pretty gutted/hard forked

Pros of V8:

  • Super portable
  • Super fast
  • Pretty much the definition of javascript

Cons of V8:

  • Only javascript

@yinzara
Copy link

yinzara commented Nov 11, 2020

So unfortunately there's a wrench in this:
eclipsesource/J2V8#441

J2V8 is reducing the scope of the project to only Android. That means there are currently no NodeJS bindings for V8. Even https://github.com/apigee/trireme is also being End of Lifed.

The only real option would be to go with GraalVM which would mean a pretty dramatic change to how FusionAuth is run.
https://mikehearn.github.io/nodejvm/

I'd really love it if we could have a real NodeJS engine (especially one with "require" for dependencies) inside of the "Lambda" functionality. It would really increase the flexibility of what could be done with FushionAuth.

@robotdan
Copy link
Member Author

We have been looking at Graal recently and so far this looks like a good option. @voidmain may have some additional thoughts.

@voidmain
Copy link
Member

GraalJS is likely the only viable option considering that numerous providers (Apple, AWS, etc) are supporting or switching to ARM and V8 and other runtimes have limited support for ARM and the bindings for those runtimes have no ARM support (as far as I can tell).

I don't think this changes a ton within FusionAuth. The GraalJS interface is the same as Hashorn for the most part. GraalJS does provide a more modern runtime that supports most of v11 (aka JS 2020).

GraalJS does support a NodeJS runtime as well, but I'm leery of adding that in. Mainly because it's huge. GraalJS core runtime is currently sitting at 40-50MB. Adding in the NodeJS could add hundreds of more MB. This would make FusionAuth much less enticing for embedded solutions. I'm also trying to rip out the ICU4J dependency if possible, but that thing is a where the bulk of the size for GraalJS comes in.

My preference is to upgrade to GraalJS and then allow developers to add additional scope to their own runtime (if possible). This would make the FusionAuth core bundles smaller but if you needed a complete NodeJS runtime or the internationalization with ICU4J, you could add those libraries to your runtime.

Here are the repository I'm working with currently:

https://github.com/graalvm/graaljs

@bradleykite
Copy link

Just as a side-note, is there a way we can just extend a Java class or something and extend FusionAuth functionality that way in addition / instead of / along-side GraalJS / V8?

A bit like the password hashing plugins that are supported.

@robotdan
Copy link
Member Author

robotdan commented Dec 7, 2020

@bradleykite Not currently, for security purposes we have explicitly prohibited all access to Java classes from within the Lambda function.

One option we've discussed is allowing global functions to be defined in a "helper" lambda that could accessed by other lambdas so that you could at least define all of your helper code in one spot.

@mooreds
Copy link
Collaborator

mooreds commented Dec 7, 2020

More feedback on this. Someone considered FusionAuth and wanted to be able to use the FireBase JS SDK to create firebase compatible tokens. FusionAuth doesn't support this at present, but if we used a more extensible JS runtime, we could offer this. The person giving feedback also pointed to this set of docs (from Auth)) as being useful for seeing what he could include in the extension points: https://auth0-extensions.github.io/canirequire/#firebase

@bradleykite
Copy link

bradleykite commented Dec 7, 2020 via email

@robotdan
Copy link
Member Author

robotdan commented Dec 7, 2020

Thanks for the clarification @bradleykite - we have intentionally not gone down this path.

There are pros and cons for sure, and there are some definite benefit to plugins, in our experience this leads to "plugin hell" where everything breaks each time you upgrade. Wordpress is a good example of this, WordPress itself may be a fine product, but as you layer on plugins, you get stuck at a version once plugins stop being updated or maintained, and there is often no way of knowing what will break until you try to upgrade.

@robotdan robotdan added this to the 1.34.0 milestone Jan 11, 2022
@robotdan robotdan modified the milestones: 1.35.0, 1.34.0 Feb 7, 2022
@robotdan robotdan modified the milestones: 1.34.0, 1.35.0 Feb 17, 2022
@robotdan
Copy link
Member Author

robotdan commented Mar 8, 2022

Initial release will be to add support for using GraalJS as an engine per lambda. You'll have the option to switch back. This will let us burn this in for a while before yanking Nashorn.

GraalJS is actually slower than Nashorn because unless you run on the GraalVM, the JS is interpreted only, and you don't get the JIT. We currently pre-compile each lambda in Nashorn, so it is really fast.

Once GraalVM starts shipping support for arm64 for M1, Graviton, etc. we will consider moving to GraalVM if it makes the Lambdas super fast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants