Skip to content

Commit

Permalink
fix: issues with new javascript engines
Browse files Browse the repository at this point in the history
  • Loading branch information
TimeBather committed Jan 3, 2025
1 parent 6ed57db commit 1de8e88
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public void unsubscribe(String eventName, Consumer<Object[]> consumer){
}

public void subscribe(String eventName, JavascriptValue consumer){
consumer = consumer.cloneValue();
consumer.pin();
functionalListeners.computeIfAbsent(eventName,(v)->new HashSet<>())
.add(consumer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,37 @@ public abstract class DOMRegistryItem {


public static DOMRegistryItem fromExecutable(JavascriptValue executable){
JavascriptValue finalExecutable = executable.cloneValue();
return new DOMRegistryItem() {
@Override
JavascriptValue render(DomContext<?, ?> document) {
return executable.execute(document);
return finalExecutable.execute(document);
}
};
}

public static DOMRegistryItem fromConfigurableObject(JavascriptValue object){
JavascriptValue finalObject = object.cloneValue();

if(!object.hasMember("render") || !object.getMember("render").canExecute()){
if(!finalObject.hasMember("render") || !finalObject.getMember("render").canExecute()){
throw new IllegalArgumentException("Object must have a render method");
}

DOMRegistryItem item = new DOMRegistryItem() {
@Override
JavascriptValue render(DomContext<?, ?> document) {
return object.invokeMember("render", document);
return finalObject.invokeMember("render", document);
}
};

if(object.hasMember("renderEngine")){
if(finalObject.hasMember("renderEngine")){
item.renderEngine = object.getMember("renderEngine").asString();
}

if(object.hasMember("lightLevel")){
if(finalObject.hasMember("lightLevel")){
item.lightLevel = object.getMember("lightLevel").asString();
}

return item;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ public interface JavascriptValue {
boolean isNumber();

int asInt();

JavascriptValue cloneValue();
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,13 @@ public boolean equals(Object object) {
public int hashCode() {
return Objects.hash(value, reciever);
}

@Override
public JavascriptValue cloneValue() {
try{
return new JavetJavascriptValue(value.toClone(), runtime);
}catch (JavetException e){
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interop.V8Runtime;
import com.caoccao.javet.interop.callback.IJavetDirectCallable;
import com.caoccao.javet.interop.callback.JavetCallbackContext;
import com.caoccao.javet.interop.callback.JavetCallbackType;
import com.caoccao.javet.interop.converters.IJavetConverter;
import com.caoccao.javet.values.V8Value;
import com.caoccao.javet.values.reference.V8ValueObject;
Expand All @@ -22,6 +24,9 @@ public class ClassAccessor {
Map<String, MethodOverrideMap> methods = new HashMap<>();
Map<String, Field> fields = new HashMap<>();

boolean isFunctionalInterface = false;
String functionalMethodName;

public ClassAccessor(
V8Runtime runtime,
IJavetConverter provider,
Expand All @@ -38,8 +43,6 @@ public Object invoke(
String name,
V8Value ...value
) throws InvocationTargetException, IllegalAccessException, JavetException {
System.gc();
runtime.lowMemoryNotification();
if(quickAccessors.containsKey(name)) {
return quickAccessors.get(name).apply(value);
}
Expand All @@ -62,7 +65,7 @@ public Object invoke(

for(int i = 0; i < valueSize ; i++) {
if(!convertMask.get(i)){
arrayParameters[i] = value[i];
arrayParameters[i] = new JavetJavascriptValue(value[i], runtime);
continue;
}
Object nativeObject = provider.toObject(value[i]);
Expand All @@ -83,7 +86,7 @@ public Object invoke(
if(values[parameterIndex] == null){
values[parameterIndex] = new JavetJavascriptValue(value[parameterIndex], runtime);
}
parameters[parameterIndex] = value[parameterIndex];
parameters[parameterIndex] = values[parameterIndex];
continue;
}

Expand All @@ -98,11 +101,9 @@ public Object invoke(
isSignatureMatch = false;
break;
}

if(!isSignatureMatch){
continue;
}

return localMethod.invoke(target, parameters);
}
throw new RuntimeException("Illegal invocation");
Expand Down Expand Up @@ -174,6 +175,8 @@ public static ClassAccessor collect(
method.getReturnType() == interfaceMethod.getReturnType()
){
filteredMethods.add(method);
accessor.isFunctionalInterface = true;
accessor.functionalMethodName = method.getName();
}
}
}
Expand Down Expand Up @@ -262,4 +265,21 @@ protected void bindProp(
);
value.bindProperty(readContext, writeContext);
}

public V8ValueObject createObject(
Object object,
IJavetConverter converter,
V8Runtime v8Runtime
) throws JavetException {
if(isFunctionalInterface){
return v8Runtime.createV8ValueFunction(new JavetCallbackContext(
"apply",
JavetCallbackType.DirectCallNoThisAndResult,
(IJavetDirectCallable.NoThisAndResult) (V8Value ...values)->{
return converter.toV8Value(v8Runtime, invoke(object, functionalMethodName, values));
}
));
}
return v8Runtime.createV8ValueObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ public FastJavetClassConverter(V8Runtime v8Runtime){
}
public HashMap<Class, V8ValueObject> classTypeCache = new HashMap<>();

public HashMap<Class, ClassAccessor> accessors = new HashMap<>();


public V8ValueObject getClassPrototype(Class<?> prototype) throws JavetException {
if(classTypeCache.containsKey(prototype))
return classTypeCache.get(prototype);
V8ValueObject prototypeObject = v8Runtime.createV8ValueObject();

ClassAccessor accessor = ClassAccessor.collect(v8Runtime, this, prototype);
accessors.put(prototype, accessor);

accessor.bindPrototypeTo(v8Runtime, this, prototypeObject);

Expand All @@ -63,6 +66,9 @@ protected <T extends V8Value> T toV8Value(V8Runtime v8Runtime, Object object, in
if(object instanceof JavetJavascriptValue value){
return (T) value.getValue().toClone();
}
if(object instanceof V8Value value){
return (T) value.toClone();
}
if(
object instanceof int[] ||
object instanceof float[] ||
Expand Down Expand Up @@ -102,14 +108,14 @@ protected <T extends V8Value> T toV8Value(V8Runtime v8Runtime, Object object, in
// Reference to object to prevent the GCs
}
));
v8ValueObject.setWeak();
}
return v8Value;
}

V8ValueObject proto = this.getClassPrototype(object.getClass());


V8ValueObject childObject = v8Runtime.createV8ValueObject();
V8ValueObject childObject = this.accessors.get(object.getClass()).createObject(object, this, v8Runtime);
int hashCode = System.identityHashCode(object);
cachedObjects.put(hashCode, new WeakReference<>(object));
childObject.setPrivateProperty("KasugaLib#Address", hashCode);
Expand All @@ -121,7 +127,7 @@ protected <T extends V8Value> T toV8Value(V8Runtime v8Runtime, Object object, in
}
));
childObject.set("__proto__",proto);

childObject.setWeak();
return (T) childObject;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static JavetCallbackContext getCallbackContext(
}

if(!className.isAssignableFrom(targetObject.getClass())) {
throw new RuntimeException("Illegal invocation");
throw new RuntimeException("Illegal invocation: "+className.getName() + "/" + targetObject.getClass().getName());
}

return converter.toV8Value(runtime ,accessor.invoke(targetObject, name, args));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,22 @@ public void tick() {
}
@HostAccess.Export
public int requestTimeout(JavascriptValue callback, JavascriptValue interval){
callback.pin();
JavascriptValue finalCallback = callback.cloneValue();
finalCallback.pin();
int[] cancelHandler = new int[1];
cancelHandler[0] = -1;
return cancelHandler[0] = requestScheduled(KasugaTimer.TimerType.TIMEOUT,()->{
this.cancelHandler.remove(cancelHandler[0]);
callback.executeVoid();
callback.unpin();
}, ()->{callback.unpin();},interval);
finalCallback.executeVoid();
finalCallback.unpin();
}, ()->{finalCallback.unpin();},interval);
}

@HostAccess.Export
public int requestInterval(JavascriptValue callback, JavascriptValue interval){
callback.pin();
return requestScheduled(KasugaTimer.TimerType.INTERVAL,()->callback.executeVoid(), ()->callback.unpin(), interval);
JavascriptValue finalCallback = callback.cloneValue();
finalCallback.pin();
return requestScheduled(KasugaTimer.TimerType.INTERVAL,()-> finalCallback.executeVoid(), ()->finalCallback.unpin(), interval);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class JavascriptMenuHandler {
private JavascriptEngineContext context;
private JavascriptValue handle;
JavascriptMenuHandler(JavascriptEngineContext context,JavascriptValue handle){
this.handle = handle;
this.handle = handle.cloneValue();
this.context = context;
}
public Runnable open(JavascriptMenuHandle handle){
Expand Down

0 comments on commit 1de8e88

Please sign in to comment.