Open tangjfn opened 4 years ago
just found another way to do it
var objectClass = org.mozilla.javascript.Context.jsToJava(java.lang.Object, java.lang.Class)
just found another way to do it
var objectClass = org.mozilla.javascript.Context.jsToJava(java.lang.Object, java.lang.Class)
thank you very mach!
js> java.lang.Object.__javaObject__;
class java.lang.Object
@tuchida thanks for pointing that out! Is there any reason why the property shouldn't just be class
instead of __javaObject__
? I think the only reason not to would be to avoid potential conflicts. However, I think that could only happen if there was a static field or method as part of the class definition named class
, which should be prohibited since "class" is a keyword.
I don't know why __javaObject__
.
which should be prohibited since "class" is a keyword.
The ECMAScript specification allows for the use of reserved words in property names.
var a = { class: 123 };
a.class; // 123
Also, Rhino specification allows shorthand notation for beans, so you can write .getClass()
as .class
.
var o = java.lang.Object();
o.class; // class java.lang.Object
o.getClass() === o.class; // true
I meant "class" should be prohibited as a java static field or method on the underlying java class, so I think there should not be a conflict when trying to access a "class" property of the NativeJavaClass via the get
method.
The NativeJavaClass represents the class itself, which is used to access static members and constructors. It doesn't have a getClass method, as only instances of Java classes do, so the shorthand does not work in this case.
I guess another reason to believe there is no chance of conflict is that java.lang.Object.class
is exactly how you would accomplish obtaining an instance of java.lang.Class that refers to java.lang.Object in Java.
I see. I think it was only in ES5 that it was specified that reserved words could be used in property names, so there must be some historical background.
It seems that even now, depending on your settings, you cannot use reserved words as identifiers. https://github.com/mozilla/rhino/blob/b0fb5f8f775127cabbd8168bfe99d6ec3c2f309f/src/org/mozilla/javascript/TokenStream.java#L755-L761
I don't think properties are identifiers, so that shouldn't be a problem.
This works in Rhino, at least when using Context.VERSION_ES6 as language level: new java.lang.String().class.getField("CASE_INSENSITIVE_ORDER")
Can this issue be closed?
@p-bakker I think this is still an issue to be addressed. It's already been pointed out above that it works on an instance of a class (because it ends up calling the .getClass()
method on the object.) The goal here is to get an instance of java.lang.Class
without first needing to instantiate an object of the target class.
I don't see any reason to not add another property to NativeJavaObject called class
that functions in exactly the same way as the __javaObject__
property. I'd just as soon change it if not for that whole backwards compatibility thing. This would make it work in the same way as a java class literal, which is the logical way to access it.
Ahh, missed that detail
Well, as all classes extend Object, Object defines a getClass() method and static methods cannot mirror instance methods and because 'class' in Java is a reserved word, so it cannot be used as the name of a (static) field, I personally don't see a (backwards or forward) compatibility issue with adding a 'class' property to NativeJavaObject that mimics the 'class' property of types in Java.
More self-explanatory than the obscure (and I think undocumented) '__javaObject__'.
Only question is from which Context.VERSION_Xxxx onwards we should, as using 'class' as a propertyName want always allowed I think
Mmm, I guess there is sort of an odd scenario: if there is a class out there that is used icw Rhino and accessing that class as a NativeJavaObject and a class defines a static void setClass(Class cls);
.
Likelyhood of that happening? Very slim if you'd ask me.
We could support that scenario by in that case making the NativeJavaObject's class
property a writable property (should be a non-writable property in all other cases I think)
Only question is from which Context.VERSION_Xxxx onwards we should, as using 'class' as a propertyName want always allowed I think
Other question: ES6 is from 2015. We are in 2024 now. Are there still use cases, where you use rhino not in ES6 mode? Could we consider removing all previous script versions with e.g. Rhino 2.0? Then we wouldn't have this problem. Alternatively, we could force at least ES6 as a requirement for LiveConnect.
For us at ServiceNow, keeping old versions around and executing code in the same way is a fundamental requirement. Changing defaults is good, but (unfortunately) we need to maintain very strong backward compatibility.
This would be nice to have, but there are a few workarounds if you need it right now.
If you have an instance of the class you want, you can call getClass() on it
You can get the current Thread's context ClassLoader and load the class from there.
If you pass
java.lang.Object
(I believe this is an instance of NativeJavaClass) as an argument to a java method, it will get converted to a java.lang.Class. So, if you need to pass it to a java method, you can let Rhino handle it for you. That also means if you are trying to get an instance of java.lang.Class to work within a Rhino script, you can do this,