Implement callable and call function in JNI layer

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2023-03-07 13:50:03 +09:00 committed by Hyukwoo Park
commit 22665e7ca2
3 changed files with 117 additions and 45 deletions

View file

@ -251,12 +251,26 @@ public class EscargotTest {
Globals.finalizeGlobals();
}
private Context initEngineAndCreateContext()
{
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
return Context.create(vmInstance);
}
private void finalizeEngine()
{
System.gc();
System.gc();
System.gc();
Memory.gc();
Memory.gc();
Globals.finalizeGlobals();
}
@Test
public void bridgeTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
class TestBridge extends Bridge.Adapter {
public boolean called = false;
@ -292,13 +306,12 @@ public class EscargotTest {
assertTrue(Evaluator.evalScript(context, "Native.returnNothing() === undefined", "from_java7.js", true).get().toString(context).get().toJavaString().equals("true"));
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void nonHeapValueTest() {
Globals.initializeGlobals();
Context context = initEngineAndCreateContext();
JavaScriptValue v = JavaScriptValue.createUndefined();
assertTrue(v.isUndefined());
@ -330,12 +343,13 @@ public class EscargotTest {
assertFalse(v.isInt32());
assertFalse(v.isUndefined());
Globals.finalizeGlobals();
context = null;
finalizeEngine();
}
@Test
public void heapValueTest() {
Globals.initializeGlobals();
Context context = initEngineAndCreateContext();
JavaScriptValue v = JavaScriptValue.create(3.14);
assertTrue(v.isNumber());
@ -348,15 +362,13 @@ public class EscargotTest {
assertFalse(v.isNumber());
assertFalse(v.isUndefinedOrNull());
Globals.finalizeGlobals();
context = null;
finalizeEngine();
}
@Test
public void valueToStringTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
Optional<JavaScriptString> result = JavaScriptValue.create(123).toString(context);
assertTrue(result.isPresent());
@ -369,16 +381,12 @@ public class EscargotTest {
assertEquals(result.get().toJavaString(), Integer.MAX_VALUE+"");
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void valueOperationTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
assertEquals(JavaScriptValue.create(123).toString(context).get().toJavaString(), "123");
assertEquals(JavaScriptValue.create(123).toBoolean(context).get(), true);
@ -392,15 +400,13 @@ public class EscargotTest {
assertTrue(context.lastThrownException().isPresent());
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void symbolValueTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.empty(), Optional.empty());
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);
JavaScriptSymbol symbol = JavaScriptValue.create(Optional.empty());
@ -425,16 +431,12 @@ public class EscargotTest {
assertTrue(symbol1.equalsTo(context, symbol2).get().booleanValue());
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void objectCreateReadWriteTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.empty(), Optional.empty());
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
JavaScriptObject obj = JavaScriptObject.create(context);
assertTrue(obj.set(context, JavaScriptValue.create("asdf"), JavaScriptValue.create(123)).get().booleanValue());
@ -446,16 +448,12 @@ public class EscargotTest {
assertTrue(obj.getOwnProperty(context, JavaScriptValue.create("qwer")).get().toNumber(context).get().doubleValue() == 123);
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void arrayCreateReadWriteTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.empty(), Optional.empty());
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
JavaScriptArrayObject arr = JavaScriptArrayObject.create(context);
assertTrue(arr.set(context, JavaScriptValue.create(3), JavaScriptValue.create(123)).get().booleanValue());
@ -464,16 +462,12 @@ public class EscargotTest {
assertTrue(arr.length(context) == 4);
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void jsonParseStringifyTest() {
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.empty(), Optional.empty());
Context context = Context.create(vmInstance);
Context context = initEngineAndCreateContext();
String testString = "[1, 2, 3]";
JavaScriptValue result = context.getGlobalObject().jsonParse(context, JavaScriptValue.create(testString)).get();
@ -491,8 +485,42 @@ public class EscargotTest {
assertEquals(context.getGlobalObject().jsonStringify(context, result).get().toJavaString(), "{\"123\":456,\"a\":\"asdf\"}");
context = null;
vmInstance = null;
Globals.finalizeGlobals();
finalizeEngine();
}
@Test
public void testCallableAndCall() {
Context context = initEngineAndCreateContext();
JavaScriptValue value = JavaScriptString.create(1123);
assertFalse(value.isCallable());
value = JavaScriptString.create("1123");
assertFalse(value.isCallable());
value = JavaScriptString.create(Optional.of(JavaScriptString.create("asdf")));
assertFalse(value.isCallable());
value = JavaScriptObject.create(context);
assertFalse(value.isCallable());
value = JavaScriptArrayObject.create(context);
assertFalse(value.isCallable());
assertFalse(context.lastThrownException().isPresent());
value.call(context, JavaScriptValue.createUndefined(), new JavaScriptValue[]{});
assertTrue(context.lastThrownException().isPresent());
value = context.getGlobalObject().asScriptObject().get(context, JavaScriptValue.create("Array")).get();
assertTrue(value.isCallable());
value = value.call(context, JavaScriptString.createUndefined(), new JavaScriptValue[]{
JavaScriptValue.create(1), JavaScriptValue.create(2), JavaScriptValue.create(3)
}).get();
assertTrue(value.isArrayObject());
assertEquals(value.asScriptArrayObject().length(context), 3);
assertEquals(value.asScriptArrayObject().get(context, JavaScriptValue.create(0)).get().asInt32(), 1);
assertEquals(value.asScriptArrayObject().get(context, JavaScriptValue.create(1)).get().asInt32(), 2);
assertEquals(value.asScriptArrayObject().get(context, JavaScriptValue.create(2)).get().asInt32(), 3);
context = null;
finalizeEngine();
}
}

View file

@ -1038,6 +1038,13 @@ Java_com_samsung_lwe_escargot_JavaScriptValue_isSymbol(JNIEnv* env, jobject thiz
return unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->isSymbol();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_isCallable(JNIEnv* env, jobject thiz)
{
return unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->isCallable();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_isObject(JNIEnv* env, jobject thiz)
@ -1312,6 +1319,34 @@ Java_com_samsung_lwe_escargot_JavaScriptValue_instanceOf(JNIEnv* env, jobject th
evaluatorResult);
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_call(JNIEnv* env, jobject thiz, jobject context,
jobject receiver, jobjectArray argv)
{
auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ValueRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz);
ValueRef* receiverValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(receiver), receiver);
auto argvLength = env->GetArrayLength(argv);
ValueRef** argVector = reinterpret_cast<ValueRef**>(Memory::gcMalloc(argvLength * sizeof(ValueRef*)));
for (jsize i = 0; i < argvLength; i++) {
jobject e = env->GetObjectArrayElement(argv, i);
argVector[i] = unwrapValueRefFromValue(env, env->GetObjectClass(e), e);
}
auto evaluatorResult = Evaluator::execute(contextRef->get(),
[](ExecutionStateRef* state, ValueRef* thisValueRef, ValueRef* receiverValueRef, ValueRef** argVector, int argvLength) -> ValueRef* {
return thisValueRef->call(state, receiverValueRef, argvLength, argVector);
}, thisValueRef, receiverValueRef, argVector, argvLength);
Memory::gcFree(argVector);
return createOptionalValueFromEvaluatorJavaScriptValueResult(env, context, contextRef->get(),
evaluatorResult);
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_toBoolean(JNIEnv* env, jobject thiz, jobject context)
@ -1515,4 +1550,3 @@ Java_com_samsung_lwe_escargot_JavaScriptGlobalObject_jsonParse(JNIEnv* env, jobj
return createOptionalValueFromEvaluatorJavaScriptValueResult(env, context, contextRef->get(),
evaluatorResult);
}

View file

@ -26,6 +26,7 @@ public class JavaScriptValue extends NativePointerHolder {
native public boolean isInt32();
native public boolean isString();
native public boolean isSymbol();
native public boolean isCallable();
native public boolean isObject();
native public boolean isArrayObject();
@ -69,4 +70,13 @@ public class JavaScriptValue extends NativePointerHolder {
* @return
*/
native public Optional<Boolean> instanceOf(Context context, JavaScriptValue other);
/**
*
* @param context
* @param receiver
* @param argv
* @return
*/
native public Optional<JavaScriptValue> call(Context context, JavaScriptValue receiver, JavaScriptValue[] argv);
}