Skip to content

Commit

Permalink
Implement setExtraData, extraData on JavaScriptObject
Browse files Browse the repository at this point in the history
Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed Oct 25, 2023
1 parent f33168c commit bd4b293
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1326,4 +1326,38 @@ public Optional<JavaScriptValue> callback(Context context, JavaScriptValue recei
finalizeEngine();
}

@Test
public void extraDataTest()
{
Globals.initializeGlobals();
VMInstance vmInstance = VMInstance.create(Optional.of("en-US"), Optional.of("Asia/Seoul"));
Context context = Context.create(vmInstance);

JavaScriptObject obj = JavaScriptObject.create(context);
assertTrue(obj.extraData() != null);
assertFalse(obj.extraData().isPresent());
obj.setExtraData(null);
assertFalse(obj.extraData().isPresent());
printNegativeTC("extraDataTest 1");

Object jObject = new Object();

obj.setExtraData(Optional.of(jObject));
assertTrue(obj.extraData().isPresent());
assertEquals(obj.extraData().get(), jObject);
obj.setExtraData(Optional.empty());
assertFalse(obj.extraData().isPresent());
printPositiveTC("promiseTest 2");

obj.setExtraData(Optional.of(jObject));
assertTrue(obj.extraData().isPresent());
assertEquals(obj.extraData().get(), jObject);
obj.setExtraData(null);
assertFalse(obj.extraData().isPresent());
printNegativeTC("promiseTest 3");

context = null;
vmInstance = null;
finalizeEngine();
}
}
26 changes: 26 additions & 0 deletions build/android/escargot/src/main/cpp/EscargotJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,30 @@ jobject createOptionalValueFromEvaluatorDoubleResult(JNIEnv* env, jobject contex
}

return storeExceptionOnContextAndReturnsIt(env, contextObject, context, evaluatorResult);
}

ScriptObjectExtraData* ensureScriptObjectExtraData(ObjectRef* ref)
{
ScriptObjectExtraData* data = reinterpret_cast<ScriptObjectExtraData*>(ref->extraData());
if (!data) {
data = new ScriptObjectExtraData;
ref->setExtraData(data);

Memory::gcRegisterFinalizer(ref, [](void* self) {
ScriptObjectExtraData* extraData = reinterpret_cast<ScriptObjectExtraData*>(reinterpret_cast<ObjectRef*>(self)->extraData());
auto env = fetchJNIEnvFromCallback();
if (env) {
if (extraData->implementSideData) {
env->DeleteGlobalRef(extraData->implementSideData);
extraData->implementSideData = nullptr;
}
if (extraData->userData) {
env->DeleteGlobalRef(extraData->userData);
extraData->userData = nullptr;
}
}
});

}
return data;
}
18 changes: 18 additions & 0 deletions build/android/escargot/src/main/cpp/EscargotJNI.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,24 @@ jobject createOptionalValueFromEvaluatorBooleanResult(JNIEnv* env, jobject conte
jobject createOptionalValueFromEvaluatorIntegerResult(JNIEnv* env, jobject contextObject, ContextRef* context, Evaluator::EvaluatorResult& evaluatorResult);
jobject createOptionalValueFromEvaluatorDoubleResult(JNIEnv* env, jobject contextObject, ContextRef* context, Evaluator::EvaluatorResult& evaluatorResult);

struct ScriptObjectExtraData {
jobject userData;
jobject implementSideData;

ScriptObjectExtraData()
: userData(nullptr)
, implementSideData(nullptr)
{
}

void* operator new(size_t t)
{
return Memory::gcMallocAtomic(sizeof(ScriptObjectExtraData));
}
};

ScriptObjectExtraData* ensureScriptObjectExtraData(ObjectRef* ref);

template<typename T>
jobject nativeOptionalValueIntoJavaOptionalValue(JNIEnv* env, OptionalRef<T> ref)
{
Expand Down
13 changes: 4 additions & 9 deletions build/android/escargot/src/main/cpp/JNIBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ Java_com_samsung_lwe_escargot_Bridge_register(JNIEnv* env, jclass clazz, jobject
ValueRef** argv,
bool isConstructorCall) -> ValueRef* {
FunctionObjectRef* callee = state->resolveCallee().get();
jobject jo = static_cast<jobject>(reinterpret_cast<FunctionObjectRef*>(callee)->extraData());

jobject jo = ensureScriptObjectExtraData(
reinterpret_cast<FunctionObjectRef*>(callee))->implementSideData;
auto env = fetchJNIEnvFromCallback();
if (!env) {
// give up
Expand Down Expand Up @@ -141,14 +143,7 @@ Java_com_samsung_lwe_escargot_Bridge_register(JNIEnv* env, jclass clazz, jobject

if (evalResult.isSuccessful()) {
FunctionObjectRef* callback = evalResult.result->asFunctionObject();
callback->setExtraData(adapter);
Memory::gcRegisterFinalizer(callback, [](void* self) {
jobject jo = static_cast<jobject>(reinterpret_cast<FunctionObjectRef*>(self)->extraData());
auto env = fetchJNIEnvFromCallback();
if (env) {
env->DeleteGlobalRef(jo);
}
});
ensureScriptObjectExtraData(callback)->implementSideData = adapter;
} else {
env->DeleteGlobalRef(adapter);
}
Expand Down
12 changes: 2 additions & 10 deletions build/android/escargot/src/main/cpp/JNIFunctionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Java_com_samsung_lwe_escargot_JavaScriptJavaCallbackFunctionObject_create(JNIEnv
}

env->PushLocalFrame(32);
jobject callback = reinterpret_cast<jobject>(state->resolveCallee()->extraData());
jobject callback = ensureScriptObjectExtraData(state->resolveCallee().get())->implementSideData;
auto callbackMethodId = env->GetMethodID(env->GetObjectClass(callback), "callback",
"(Lcom/samsung/lwe/escargot/Context;Lcom/samsung/lwe/escargot/JavaScriptValue;[Lcom/samsung/lwe/escargot/JavaScriptValue;)Ljava/util/Optional;");

Expand Down Expand Up @@ -107,14 +107,6 @@ Java_com_samsung_lwe_escargot_JavaScriptJavaCallbackFunctionObject_create(JNIEnv

callback = env->NewGlobalRef(callback);
FunctionObjectRef* fn = evaluatorResult.result->asFunctionObject();
fn->setExtraData(callback);
Memory::gcRegisterFinalizer(fn, [](void* self) {
jobject jo = static_cast<jobject>(reinterpret_cast<FunctionObjectRef*>(self)->extraData());
auto env = fetchJNIEnvFromCallback();
if (env) {
env->DeleteGlobalRef(jo);
}
});

ensureScriptObjectExtraData(fn)->implementSideData = callback;
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptJavaCallbackFunctionObject", fn);
}
45 changes: 45 additions & 0 deletions build/android/escargot/src/main/cpp/JNIObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,49 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_getOwnProperty(JNIEnv* env, jobje

return createOptionalValueFromEvaluatorJavaScriptValueResult(env, context, contextRef->get(),
evaluatorResult);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_samsung_lwe_escargot_JavaScriptObject_setExtraData(JNIEnv* env, jobject thiz,
jobject object)
{
ObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asObject();
jobject extraData = nullptr;

if (object) {
auto classOptional = env->GetObjectClass(object);
auto methodIsPresent = env->GetMethodID(classOptional, "isPresent", "()Z");
if (env->CallBooleanMethod(object, methodIsPresent)) {
auto methodGet = env->GetMethodID(classOptional, "get", "()Ljava/lang/Object;");
jboolean isSucceed;
extraData = env->CallObjectMethod(object, methodGet);
extraData = env->NewGlobalRef(extraData);
}
}

ensureScriptObjectExtraData(thisValueRef)->userData = extraData;
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptObject_extraData(JNIEnv* env, jobject thiz)
{
ObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asObject();
jobject extraData = nullptr;
if (thisValueRef->extraData()) {
extraData = ensureScriptObjectExtraData(thisValueRef)->userData;
}

jclass optionalClazz = env->FindClass("java/util/Optional");
if (extraData) {
return env->CallStaticObjectMethod(optionalClazz,
env->GetStaticMethodID(optionalClazz, "of",
"(Ljava/lang/Object;)Ljava/util/Optional;"),
extraData);
} else {
return env->CallStaticObjectMethod(optionalClazz,
env->GetStaticMethodID(optionalClazz, "empty",
"()Ljava/util/Optional;"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,17 @@ public native Optional<Boolean> defineDataProperty(Context context, JavaScriptVa
* @return JavaScriptValue or Optional.empty if there was a exception while executing getOwnProperty function
*/
public native Optional<JavaScriptValue> getOwnProperty(Context context, JavaScriptValue propertyName);

/**
* store Java Object in JavaScriptObject
* @param object
*/
public native void setExtraData(Optional<Object> object);

/**
* returns stored Java object in JavaScriptObject
* this function returns `Optional with Object` or `empty Optional`
* @return
*/
public native Optional<Object> extraData();
}

0 comments on commit bd4b293

Please sign in to comment.