feat: add support for member class wrappers
This commit is contained in:
parent
7e6a1e03c8
commit
6da7720c67
@ -8,7 +8,6 @@ import me.topchetoeu.jscript.engine.CallContext.DataKey;
|
||||
import me.topchetoeu.jscript.engine.debug.DebugState;
|
||||
import me.topchetoeu.jscript.engine.modules.ModuleManager;
|
||||
import me.topchetoeu.jscript.engine.scope.GlobalScope;
|
||||
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||
import me.topchetoeu.jscript.engine.values.ObjectValue.PlaceholderProto;
|
||||
@ -181,7 +180,7 @@ public class Engine {
|
||||
return msg.notifier;
|
||||
}
|
||||
|
||||
public CodeFunction compile(GlobalScope scope, String filename, String raw) throws InterruptedException {
|
||||
public FunctionValue compile(GlobalScope scope, String filename, String raw) throws InterruptedException {
|
||||
return Parsing.compile(scope, filename, raw);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
|
||||
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Native {
|
||||
public String value() default "";
|
||||
|
@ -71,15 +71,45 @@ public class NativeTypeRegister {
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void applyClasses(boolean member, ObjectValue target, Class<?> clazz) {
|
||||
for (var cl : clazz.getDeclaredClasses()) {
|
||||
if (!Modifier.isStatic(cl.getModifiers()) != member) continue;
|
||||
var nat = cl.getAnnotation(Native.class);
|
||||
|
||||
if (nat != null) {
|
||||
var name = nat.value();
|
||||
if (name.equals("")) name = cl.getSimpleName();
|
||||
|
||||
var getter = new OverloadFunction("get " + name).add(Overload.getter(member ? clazz : null, (ctx, thisArg, args) -> {
|
||||
return ctx.engine().typeRegister().getConstr(cl);
|
||||
}));
|
||||
|
||||
target.defineProperty(name, getter, null, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a prototype for the given class.
|
||||
* The returned object will have appropriate wrappers for all instance members.
|
||||
* All accessors and methods will expect the this argument to be a native wrapper of the given class type.
|
||||
* @param clazz The class for which a prototype should be generated
|
||||
*/
|
||||
public static ObjectValue makeProto(Class<?> clazz) {
|
||||
var res = new ObjectValue();
|
||||
|
||||
applyMethods(true, res, clazz);
|
||||
applyFields(true, res, clazz);
|
||||
applyClasses(true, res, clazz);
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Generates a constructor for the given class.
|
||||
* The returned function will have appropriate wrappers for all static members.
|
||||
* When the function gets called, the underlying constructor will get called, unless the constructor is inaccessible.
|
||||
* @param clazz The class for which a constructor should be generated
|
||||
*/
|
||||
public static FunctionValue makeConstructor(Class<?> clazz) {
|
||||
FunctionValue func = new OverloadFunction(clazz.getName());
|
||||
|
||||
@ -94,16 +124,24 @@ public class NativeTypeRegister {
|
||||
|
||||
applyMethods(false, func, clazz);
|
||||
applyFields(false, func, clazz);
|
||||
applyClasses(false, func, clazz);
|
||||
|
||||
func.special = true;
|
||||
|
||||
return func;
|
||||
}
|
||||
/**
|
||||
* Generates a namespace for the given class.
|
||||
* The returned function will have appropriate wrappers for all static members.
|
||||
* This method behaves almost like {@link NativeTypeRegister#makeConstructor}, but will return an object instead.
|
||||
* @param clazz The class for which a constructor should be generated
|
||||
*/
|
||||
public static ObjectValue makeNamespace(Class<?> clazz) {
|
||||
ObjectValue res = new ObjectValue();
|
||||
|
||||
applyMethods(false, res, clazz);
|
||||
applyFields(false, res, clazz);
|
||||
applyClasses(false, res, clazz);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public class Overload {
|
||||
IllegalArgumentException;
|
||||
}
|
||||
|
||||
public final Overload.OverloadRunner runner;
|
||||
public final OverloadRunner runner;
|
||||
public final boolean variadic;
|
||||
public final Class<?> thisArg;
|
||||
public final Class<?>[] params;
|
||||
@ -52,8 +52,15 @@ public class Overload {
|
||||
);
|
||||
}
|
||||
|
||||
public static Overload getter(Class<?> thisArg, OverloadRunner runner) {
|
||||
return new Overload(
|
||||
(ctx, th, args) -> runner.run(ctx, th, args), false,
|
||||
thisArg,
|
||||
new Class[0]
|
||||
);
|
||||
}
|
||||
|
||||
public Overload(Overload.OverloadRunner runner, boolean variadic, Class<?> thisArg, Class<?> args[]) {
|
||||
public Overload(OverloadRunner runner, boolean variadic, Class<?> thisArg, Class<?> args[]) {
|
||||
this.runner = runner;
|
||||
this.variadic = variadic;
|
||||
this.thisArg = thisArg;
|
||||
|
Loading…
Reference in New Issue
Block a user