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

Support for GraalJS engine #85 #87

Merged
merged 6 commits into from
May 31, 2019
Merged

Conversation

mellster2012
Copy link
Contributor

Hi Max,

This PR makes minimal changes to the NashornSandboxImpl, most modified files are test files, adding a GraalJS test for each test while leaving the original tests unmodified. The GraalSandboxImpl inherits most features from the NashornSandboxImpl with the exception of a few overrides. It's not necessarily the cleanest solution and we can keep working with our internal fork while migrating to GraalVM, but creating and maintaining a fully separate fork/project would either require a lot of base refactoring for both projects or lead to a lot of duplicated code for the GraalJS version. The engines are similar enough in behavior that we could probably make just few backwards-compatible continuous changes (gearing it more towards GraalJS) while Oracle is phasing out Nashorn (which is static at this point) gradually and starts shipping GraalJS. Take a look and let me know what you think, feel free to make edits.
cheers

Copy link
Contributor

@everestbt everestbt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, I have taken an interest in the Graal implementation of this. I had a review of the changes and I am worried about some of the changes to the handling of securing bindings. Perhaps there are some differences in the way in which GraalJS handles bindings, so if you could clarify your reasoning behind certain changes here it would be appreciated.

return new GraalSandboxImpl();
}

public static NashornSandbox create(String... args) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this file include equivalent javadocs?

}

@Override
protected Bindings secureBindings(Bindings bindings) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method appears to be doing the opposite of what the other is doing, adding everything it sees to the cached bindings.

I am not sure any of these methods need to be overridden as the bindings behaviour seems much the same. These look like they are trying to do a cached bindings version instead, in which case a non-sandboxed implementation would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently we can only use one set of bindings in GraalJS due to the limitations that objects cannot be shared across bindings/contexts (except for primitives). Once Graal adds support for this we can remove these overrides.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm the behaviour here then,

If a binding for "a" -> "b" is passed in to eval, will that persist between each call of eval?

If it does that is not really desired since that can lead to a leak from one script to another.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - I fixed the bindings leak from one script to another. Thanks!


@Override
protected void resetEngineBindings() {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This again does not allow for bindings to be reset which is a problem for secured bindings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oracle/graal#631, oracle/graaljs#47 and oracle/graaljs#146 prevent resetting of bindings for GraalJS the way NashornSadbox does it for the Nashorn engine. You'd run into Exception like these: org.graalvm.polyglot.PolyglotException: java.lang.IllegalArgumentException: Values cannot be passed from one context to another. The current value originates from context 0x7ba8c737 and the argument originates from context 0x74294adb.

if (engineBindings.get(key) != null) contextBindings.remove(key);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do these lines aim to do, and if they meet a need why not have it in the other method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a script context is provided, its bindings will be evaluated later - i.e. inside the script engine - and merged into the engine bindings. Nashorn automatically checks against global bindings but Graal seems to override global binding entries if the same key is present in the script context's bindings. This will prevent overriding globals. We don't know if this is intentional behavior by GraalJS.

@mellster2012
Copy link
Contributor Author

@everestbt Thanks for the feedback - I'll take a more detailed look later, address specific comments and apply suggested changes. The main reason for the "strange" overriding behavior is due to oracle/graal#631 and oracle/graaljs#146 which makes sharing objects across contexts (every Bindings object is a new context) impossible. Thus we have to merge passed additional (simple) bindings into the current engine bindings. If and when GraalJS allows sharing objects across multiple context we can simply remove the current overrides and everything should work.

@mellster2012
Copy link
Contributor Author

@everestbt package private changes and comments have been applied.

@everestbt
Copy link
Contributor

@mellster2012 Thank you for the clarification, the choices made make a lot of sense and when/if they are brought closer it allows for very easy combining of the methods.

I have just posted one further question on the leak of bindings, thank you.

@mellster2012
Copy link
Contributor Author

@everestbt The bindings leak has been fixed. Pls. review and let me know if you have any other concerns - thx!

@mellster2012
Copy link
Contributor Author

@mxro @everestbt any comments or updates? Thx.

@mxro
Copy link
Collaborator

mxro commented May 26, 2019

Looking all good to me! Thank you @mellster2012 .

@everestbt All good to be merged from your view?

@everestbt
Copy link
Contributor

@mxro @mellster2012 All looks good from my angle. I have not had a chance to mess around with it too much but should be able to shortly. I think it is a great idea to merge it.

May be worth noting on the release that the GraalJS implementation is initial.

@mellster2012
Copy link
Contributor Author

@mxro @everestbt sounds good - Max, can you merge the conflicting test and add a comment to the release that the GraalJS implementation is initial? Thanks!

@mxro mxro merged commit 8ff8370 into javadelight:master May 31, 2019
mxro pushed a commit that referenced this pull request May 31, 2019
@mxro
Copy link
Collaborator

mxro commented May 31, 2019

Merged and released. Thank you!

@mxro
Copy link
Collaborator

mxro commented Jun 1, 2019

I have published the merged version to maven central under the version 0.1.23.

After this, I did some refactoring work and moved the Graal Js related code into a new module: https://github.com/javadelight/delight-graaljs-sandbox

This module has a dependency on Nashorn Sandbox and reuses the NashornSandboxImpl class from there.

I did this because of the following:

  1. When starting to update the readme for the Nashorn Sandbox repo I noticed that things would become a little bit confusing when the two sandboxes are mentioned alongside each other.
  2. I noticed that linking to GraalJs introduced quite heavy dependencies to the Nashorn Sandbox module. This would bulk up all projects that use the Nashorn Sandbox even if they are not interested in using the Graal JS sandbox.
  3. I find it a bit cleaner in terms of separation of concerns to move the GraalJs functionality into its own module.

I have set up a CI pipeline for the graaljs sandbox and published the module on BinTray. A request to have it included in Maven central is currently pending.

I think ideally we could have a third package 'js-sandbox' from which both Nashorn Sandbox and GraalJs sandbox import. But I think that may be a project for another day.

@mellster2012
Copy link
Contributor Author

Perfect - I was going to suggest module separation as next step to avoid unnecessary dependencies. Thanks!

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

Successfully merging this pull request may close these issues.

None yet

3 participants