GraalJs - call constructor of java object - graalvm

I want to use graal js to provide some scripting extension to my application
How can i initialize a new java object on the javascript side?
Context ctx = Context ctx = Context.newBuilder().allowHostAccess(HostAccess.ALL).allowAllAccess(true).build().create();
Value binding = ctx.getBindings("js");
binding.putMember("ArrayList", ArrayList.class);
ctx.eval("js","let list = new ArrayList();list.add(\"1\")");
List list = binding.getMember("list").as(List.class);
assert list.size() == 1;
following code throws exception
Exception in thread "main" TypeError: instantiate on JavaClass[java.util.ArrayList] failed due to: Message not supported.
at <js> :program(Unnamed:1:13-27)
at org.graalvm.polyglot.Context.eval(Context.java:371)
Running graalvm-ce-java11 19.3.2

You need to use Java.type.
Here is an example taken from https://www.graalvm.org/docs/reference-manual/polyglot/
var array = new (Java.type("int[]"))(4);
array[2] = 42;
console.log(array[2])
Here is a fully runnable example tested with GraalVM 20.0.0
import org.graalvm.polyglot.*;
class M {
public static void main(String[] args) {
try (Context context = Context.newBuilder().allowAllAccess(true).build()) {
java.util.ArrayList v = context.eval("js",
"var ArrayList = Java.type('java.util.ArrayList');" +
"var list = new ArrayList();" +
"list.add(1); list").asHostObject();
System.out.println(v.get(0));
assert v.get(0).equals(1);
}
}
}
Run with
graalvm-ce-java8-20.0.0/bin/javac M.java
graalvm-ce-java8-20.0.0/bin/java -ea M
To get 1 as output.

You could also use the sj4js library. There you can define constructors which seamlessly blend into JS.
// we create a new JS engine and add
// TestClass as a constructor. This constructor is added to globalThis such that it
// can be called as a costructor.
try (JScriptEngine engine = new JScriptEngine(new JsGlobalThis(),"gt")) {
engine.addConstructor(new TestClass("empty"));
/* call your js code here */
}
Your JS code than looks like this you would expect it.
// we create a new variable from the constructor
var tc = new TestClass("test");
console.log(tc.name)
// test

Related

Jenkins scripted Pipeline: How to apply #NonCPS annotation in this specific case

I am working on a scripted Jenkins-Pipeline that needs to write a String with a certain encoding to a file as in the following example:
class Logger implements Closeable {
private final PrintWriter writer
[...]
Logger() {
FileWriter fw = new FileWriter(file, true)
BufferedWriter bw = new BufferedWriter(fw)
this.writer = new PrintWriter(bw)
}
def log(String msg) {
try {
writer.println(msg)
[...]
} catch (e) {
[...]
}
}
}
The above code doesn't work since PrintWriter ist not serializable so I know I got to prevent some of the code from being CPS-transformed. I don't have an idea on how to do so, though, since as far as I know the #NonCPS annotation can only be applied to methods.
I know that one solution would be to move all output-related code to log(msg) and annotate the method but this way I would have to create a new writer every time the method gets called.
Does someone have an idea on how I could fix my code instead?
Thanks in advance!
Here is a way to make this work using a log function that is defined in a shared library in vars\log.groovy:
import java.io.FileWriter
import java.io.BufferedWriter
import java.io.PrintWriter
// The annotated variable will become a private field of the script class.
#groovy.transform.Field
PrintWriter writer = null
void call( String msg ) {
if( ! writer ) {
def fw = new FileWriter(file, true)
def bw = new BufferedWriter(fw)
writer = new PrintWriter(bw)
}
try {
writer.println(msg)
[...]
} catch (e) {
[...]
}
}
After all, scripts in the vars folder are instanciated as singleton classes, which is perfectly suited for a logger. This works even without #NonCPS annotation.
Usage in pipeline is as simple as:
log 'some message'

Accessing static class variable in foreach context in vala

I originally wanted to use static in method but, since it does not exists in vala, i'm trying to have a static object.
The only problem is that i got this error
utils.vala:112.11-112.57: error: invocation not supported in this context
Synapse.Utils.spec_char_map (_chrs[0], _chrs[1]);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For above code
namespace Synapse
{
namespace Utils
{
static Gee.HashMap spec_char_map;
public static void map_special_chars (ref string query) {
if (null == spec_char_map)
{
message("INIIIIT");
spec_char_map = new Gee.HashMap<char, char> ();
var spec_char_table = "ъ=-,Ь=-,Ъ=-,ь=-";
foreach (var spec_char in spec_char_table.split (","))
{
var _chrs = spec_char.split ("=");
spec_char_map (_chrs[0], _chrs[1]);
}
}
}
}
}
What is this error for, why I can't make use of my Hashtable in the foreach context ? Is there a simpler solution for what i want to do ?
This is not the correct syntax to put something in a hashmap. Use:
spec_char_map.set (_chrs[0], _chrs[1]);
or
spec_char_map[_chrs[0]] = _chrs[1];
Also, consider using GLib.Once to create a thread-safe initialiser.

Interception Using StructureMap 3.*

I've done interception using Castle.DynamicProxy and StructureMap 2.6 API but now can't do it using StructureMap 3.0. Could anyone help me find updated documentation or even demo? Everything that I've found seems to be about old versions. e.g. StructureMap.Interceptors.TypeInterceptor interface etc.
HAHAA! I f***in did it! Here's how:
public class ServiceSingletonConvention : DefaultConventionScanner
{
public override void Process(Type type, Registry registry)
{
base.Process(type, registry);
if (type.IsInterface || !type.Name.ToLower().EndsWith("service")) return;
var pluginType = FindPluginType(type);
var delegateType = typeof(Func<,>).MakeGenericType(pluginType, pluginType);
// Create FuncInterceptor class with generic argument +
var d1 = typeof(FuncInterceptor<>);
Type[] typeArgs = { pluginType };
var interceptorType = d1.MakeGenericType(typeArgs);
// -
// Create lambda expression for passing it to the FuncInterceptor constructor +
var arg = Expression.Parameter(pluginType, "x");
var method = GetType().GetMethod("GetProxy").MakeGenericMethod(pluginType);
// Crate method calling expression
var methodCall = Expression.Call(method, arg);
// Create the lambda expression
var lambda = Expression.Lambda(delegateType, methodCall, arg);
// -
// Create instance of the FuncInterceptor
var interceptor = Activator.CreateInstance(interceptorType, lambda, "");
registry.For(pluginType).Singleton().Use(type).InterceptWith(interceptor as IInterceptor);
}
public static T GetProxy<T>(object service)
{
var proxyGeneration = new ProxyGenerator();
var result = proxyGeneration.CreateInterfaceProxyWithTarget(
typeof(T),
service,
(Castle.DynamicProxy.IInterceptor)(new MyInterceptor())
);
return (T)result;
}
}
The problem here was that SM 3.* allows interception for known types, i.e. doing something like this:
expression.For<IService>().Use<Service>().InterceptWith(new FuncInterceptor<IService>(service => GetProxyFrom(service)));
But what if you'd like to include the interception logic inside your custom scanning convention where you want to intercept all instances of type with specific signature (types having name ending on 'service', in my case)?
That's what I've accomplished using Expression API and reflection.
Also, I'm using here Castle.DinamicProxy for creating proxy objects for my services.
Hope someone else will find this helpful :)
I find the best place to go for any new versions is directly to the source.
If it's written well, then it will include test cases. Thankfully structuremap does include test cases.
You can explore the tests here
In the meantime I've written an example of an Activator Interceptor, and how to configure it.
static void Main()
{
ObjectFactory.Configure(x =>
{
x.For<Form>().Use<Form1>()
.InterceptWith(new ActivatorInterceptor<Form1>(y => Form1Interceptor(y), "Test"));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
public static void Form1Interceptor(Form f)
{
//Sets the title of the form window to "Testing"
f.Text = "Testing";
}
EDIT:
How to use a "global" filter using PoliciesExpression
[STAThread]
static void Main()
{
ObjectFactory.Configure(x =>
{
x.Policies.Interceptors(new InterceptorPolicy<Form>(new FuncInterceptor<Form>(y => Intercept(y))));
});
Application.Run(ObjectFactory.GetInstance<Form>());
}
private static Form Intercept(Form form)
{
//Do the interception here
form.Text = "Testing";
return form;
}

Get private variable by reflection in dart

I would like to get private variable in an object in dart.
This variable has no getter so I want to do this with reflection.
I try many way but nothing works to me.
For exemple, when I do this:
var reflection = reflect(this);
InstanceMirror field = reflection.getField(new Symbol(fieldName));
I get an error:
No getter for fieldName.
It's normal because the variable hasn't getter.
How can I get this variable ?
EDIT with a test code:
Here is my reflect test (test variable is a reflectClass(MyClass))
reflectClass(Injector).declarations.keys.forEach((e) => test.getField(e, test.type.owner))
I get this error:
Class '_LocalInstanceMirror' has no instance method 'getField' with
matching arguments.
If I do this:
reflectClass(Injector).declarations.keys.forEach((e) => test.getField(e))
I get:
Class 'DynamicInjector' has no instance getter
'_PRIMITIVE_TYPES#0x1b5a3f8d'.
Same thing with values of declarations.
The error message you got is actually correct. The class has a getter for this field.
Dart implicitly creates getters for all and setters for all non-final/non-const fields.
It seems access to private members isn't yet supported in Dart2JS.
see https://code.google.com/p/dart/issues/detail?id=13881
Here an example how to access private fields:
(example from https://code.google.com/p/dart/issues/detail?id=16773)
import 'dart:mirrors';
class ClassWithPrivateField {
String _privateField;
}
void main() {
ClassMirror classM = reflectClass(ClassWithPrivateField);
Symbol privateFieldSymbol;
Symbol constructorSymbol;
for (DeclarationMirror declaration in classM.declarations.values) {
if (declaration is VariableMirror) {
privateFieldSymbol = declaration.simpleName;
} else if (declaration is MethodMirror && declaration.isConstructor) {
constructorSymbol = declaration.constructorName;
}
}
// it is not necessary to create the instance using reflection to be able to
// access its members with reflection
InstanceMirror instance = classM.newInstance(constructorSymbol, []);
// var s = new Symbol('_privateField'); // doesn't work for private fields
// to create a symbol for a private field you need the library
// if the class is in the main library
// var s = MirrorSystem.getSymbol('_privateField', currentMirrorSystem().isolate.rootLibrary);
// or simpler
// var s = MirrorSystem.getSymbol('_privateField', instance.type.owner);
for (var i=0; i<1000; ++i) {
instance.setField(privateFieldSymbol, 'test');
print('Iteration ${instance.getField(privateFieldSymbol)}');
}
}
using dson or serializable you can do it in next way:
library example_lib;
import 'package:dson/dson.dart';
// this should be the name of your file
part 'example.g.dart';
#serializable
class Example extends _$ExampleSerializable {
var _privateVar;
}
main() {
var example = new Example();
example['_privateVar'] = 'some value';
print('example._privateVar: ${example._privateVar}');
print('example["_privateVar"]: ${example["_privateVar']}");
}

Inconsistent error reporting from Dart Editor regarding final fields

Given the following class, Dart Editor (build 5549) gives me some conflicting feedback (per the comments in the constructor body):
class Example {
final int foo;
Example() :
foo = 0
{
foo = 1; // 'cannot assign value to final variable "foo"'
this.foo = 2; // ok
}
}
Even more confusingly, it will happily generate equivalent (working) javascript for both lines. The situation seems to be the same with methods as it is with the constructor; this especially leads me to believe that it was intended to be disallowed in both cases.
The Dart Style Guide suggests using public final fields instead of private fields with public getters. I like this in theory, but non-trivial member construction can't really go into the initializer list.
Am I missing a valid reason for the former to be reported as an error while the latter is not? Or should I be filing a bug right now?
This is surely a bug in the JavaScript generator if you run the following in the Dart VM:
main() {
new Example();
}
class Example {
final int foo;
Example() : foo = 0 {
foo = 1; // this fails in the dart vm
this.foo = 2; // this also fails in the dart vm
}
}
then it refuses to execute both the line foo = 1 and this.foo = 2. This is consistent with the spec which requires (if I read it correctly) that final fields to be final in the constructor body.

Resources