Fix Java Class objects being wrapped as NativeJavaObject#66
Conversation
When Java Class objects get passed from JS to Java they are incorrectly wrapped in NativeJavaObject instead of NativeJavaClass. This PR fixes that.
|
Well I think this is intentional, wrapping any |
Yeah it's definitely not a solution to just wrap every class as NJC, it would likely have to go through the class filter somehow (but iirc that is implemented on KubeJS' side?) |
|
The behavior on the JS side doesn't change at all. All loadable Java classes are already accessible by design, like this: let $ListTag = Java.loadClass("net.minecraft.nbt.ListTag")
const listTagClass = $ListTag.__javaObject__
console.log(listTagClass)You can see all the Class methods if you do: console.log(JSON.stringify(listTagClass, null, 2))You can call most Class methods on it, but importantly, you can't call any caller sensitive methods, which are the methods that do the actual potentially security-breaking reflection. So basically you can just call I actually found this NativeJavaClass bug while making a mod to allow for reflection in kube: https://github.com/lonevox/KubeJS-Reflected Also you cannot ever get a usable reference to banned classes from Java. The class filter doesn't allow banned classes to be sent from Java to JS. It doesn't matter if it's wrapped as a NativeJavaObject or a NativeJavaClass. My mod has to circumvent the class filter to make reflection work. |
I believe there's no such issue. Class<?> clazz;
if (jsObj instanceof NativeJavaClass njc) {
clazz = ...;
}I would recommend: Class<?> clazz;
if (jsObj instanceof Wrapper wrapper && wrapper.unwrap() instanceof Class c) {
clazz = c;
}
// or alternatively:
if (Wrapper.unwrapped(jsObj) instanceof Class c) {
clazz = c;
}Also I'm curious, JS objects will be automatically unwrapped and transformed when accessing Java method/field, why would you need to unwrap it manually? |
Because specifically private void expectsClass(Class<?> clazz) {
System.out.println(clazz.isArray());
}I'm unsure if the above is even possible without circumventing the class filter though, so I admit this is a very specific issue that probably only I will even run into. So if it's worth merging, idk, I currently fix it myself with a mixin so I'm not that bothered. Just thought I might as well contribute the fix. |
I might met something similar. /** @type {typeof import("vectorwing.farmersdelight.common.block.RotatedFeastBlock").$RotatedFeastBlock } */
let $RotatedFeastBlock = Java.loadClass("vectorwing.farmersdelight.common.block.RotatedFeastBlock")
/** @type {typeof import("vectorwing.farmersdelight.common.registry.ModItems").$ModItems } */
let $ModItems = Java.loadClass("vectorwing.farmersdelight.common.registry.ModItems")
/** @type {typeof import("vectorwing.farmersdelight.common.BlockShapes").$BlockShapes } */
let $BlockShapes = Java.loadClass("vectorwing.farmersdelight.common.BlockShapes")
StartupEvents.registry('block', event => {
console.log($BlockShapes.SHEPHERDS_PIE_SHAPES)
console.log($BlockShapes.TRAY_SHAPE)
COTTAGE_PIE_BLOCK = event.createCustom('farmersdelight:cottage_pie_block',
() => new $RotatedFeastBlock(
$BlockBehaviour$Properties.ofFullCopy(Blocks.CAKE), $ModItems.SHEPHERDS_PIE, true,
$BlockShapes.SHEPHERDS_PIE_SHAPES, $BlockShapes.TRAY_SHAPE
)
)
})This script ran into problems and here's the log: https://mclo.gs/8OtmX5X This PR might fix this problem? |
When Java Class objects get passed from JS to Java they are incorrectly wrapped in NativeJavaObject instead of NativeJavaClass. This PR fixes that.