Skip to content

Commit

Permalink
Implement JavaErrorObject in JNI
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 Nov 1, 2023
1 parent d7cf6a5 commit 2ecb52c
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 8 deletions.
7 changes: 1 addition & 6 deletions build/android/.gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/*
.DS_Store
/build
/captures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ public TestSet(JavaScriptValue value, String[] okMethodNames)
new TestSet(JavaScriptObject.create(context), new String[]{"asScriptObject"}),
new TestSet(JavaScriptArrayObject.create(context), new String[]{"asScriptObject", "asScriptArrayObject"}),
new TestSet(JavaScriptPromiseObject.create(context), new String[]{"asScriptObject", "asScriptPromiseObject"}),
new TestSet(JavaScriptErrorObject.create(context, JavaScriptErrorObject.ErrorKind.EvalError, "asdf"), new String[]{"asScriptObject", "asScriptErrorObject"}),
new TestSet(JavaScriptJavaCallbackFunctionObject.create(context, "", 0, false, new JavaScriptJavaCallbackFunctionObject.Callback() {
@Override
public Optional<JavaScriptValue> callback(Context context, JavaScriptValue receiverValue, JavaScriptValue[] arguments) {
Expand Down Expand Up @@ -1046,6 +1047,7 @@ public Optional<JavaScriptValue> callback(Context context, JavaScriptValue recei
return Optional.of(JavaScriptValue.create(arguments.length));
}
});
callbackFunctionObject.setExtraData(Optional.of(new Object()));

context.getGlobalObject().set(context, JavaScriptString.create("asdf"), callbackFunctionObject);

Expand Down Expand Up @@ -1082,6 +1084,7 @@ public Optional<JavaScriptValue> callback(Context context, JavaScriptValue recei
return Optional.of(JavaScriptValue.create(sum));
}
});
callbackFunctionObject.setExtraData(Optional.of(new Object()));
context.getGlobalObject().set(context, JavaScriptString.create("asdf"), callbackFunctionObject);

ret = Evaluator.evalScript(context, "asdf(1, 2, 3, 4)", "test.js", false);
Expand Down Expand Up @@ -1778,4 +1781,26 @@ public JavaScriptValue build(Context scriptContext, MultiThreadExecutor.ResultBu
finalizeEngine();
}

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

JavaScriptErrorObject e = JavaScriptErrorObject.create(context, JavaScriptErrorObject.ErrorKind.None, "test");
assertTrue(e.isErrorObject());
assertTrue(e.toString(context).get().toJavaString().equals("Error: test"));

JavaScriptErrorObject.ErrorKind[] kinds = JavaScriptErrorObject.ErrorKind.values();
for (int i = 1 /* skip None */; i < kinds.length; i ++) {
e = JavaScriptErrorObject.create(context, kinds[i], "test" + i);
assertTrue(e.isErrorObject());
assertTrue(e.toString(context).get().toJavaString().equals(kinds[i].name() + ": test" + i));
}

context = null;
vmInstance = null;
finalizeEngine();
}
}
19 changes: 18 additions & 1 deletion build/android/escargot/src/main/cpp/EscargotJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ jobject createJavaObjectFromValue(JNIEnv* env, ValueRef* value)
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptGlobalObject", value);
} else if (value->isFunctionObject()) {
if (value->asFunctionObject()->extraData()) {
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptJavaCallbackFunctionObject", value);
ScriptObjectExtraData* data = reinterpret_cast<ScriptObjectExtraData*>(value->asFunctionObject()->extraData());
if (data->implementSideData) {
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptJavaCallbackFunctionObject", value);
}
}
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptFunctionObject", value);
} else if (value->isPromiseObject()) {
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptPromiseObject", value);
} else if (value->isErrorObject()) {
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptErrorObject", value);
} else {
return createJavaValueObject(env, "com/samsung/lwe/escargot/JavaScriptObject", value);
}
Expand Down Expand Up @@ -155,6 +160,18 @@ StringRef* createJSStringFromJava(JNIEnv* env, jstring str)
return code;
}

std::string createStringFromJava(JNIEnv* env, jstring str)
{
if (!str) {
return std::string();
}
jboolean isSucceed;
const char* cString = env->GetStringUTFChars(str, &isSucceed);
std::string ret = std::string(cString, env->GetStringUTFLength(str));
env->ReleaseStringUTFChars(str, cString);
return ret;
}

jstring createJavaStringFromJS(JNIEnv* env, StringRef* string)
{
std::basic_string<uint16_t> buf;
Expand Down
1 change: 1 addition & 0 deletions build/android/escargot/src/main/cpp/EscargotJNI.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ OptionalRef<JNIEnv> fetchJNIEnvFromCallback();

std::string fetchStringFromJavaOptionalString(JNIEnv *env, jobject optional);
StringRef* createJSStringFromJava(JNIEnv* env, jstring str);
std::string createStringFromJava(JNIEnv* env, jstring str);
jstring createJavaStringFromJS(JNIEnv* env, StringRef* string);
void throwJavaRuntimeException(ExecutionStateRef* state);
jobject storeExceptionOnContextAndReturnsIt(JNIEnv* env, jobject contextObject, ContextRef* context, Evaluator::EvaluatorResult& evaluatorResult);
Expand Down
63 changes: 63 additions & 0 deletions build/android/escargot/src/main/cpp/JNIErrorObject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023-present Samsung Electronics Co., Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/

#include "EscargotJNI.h"

extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptErrorObject_create(JNIEnv* env, jclass clazz,
jobject context, jobject kind,
jstring message)
{
THROW_NPE_RETURN_NULL(context, "Context");
THROW_NPE_RETURN_NULL(kind, "ErrorKind");
THROW_NPE_RETURN_NULL(message, "String");

auto nameMethod = env->GetMethodID(env->GetObjectClass(kind), "name", "()Ljava/lang/String;");
auto kindName = (jstring)env->CallObjectMethod(kind, nameMethod);
auto string = createStringFromJava(env, kindName);

ErrorObjectRef::Code code = Escargot::ErrorObjectRef::None;
if (string == "ReferenceError") {
code = Escargot::ErrorObjectRef::ReferenceError;
} else if (string == "TypeError") {
code = Escargot::ErrorObjectRef::TypeError;
} else if (string == "SyntaxError") {
code = Escargot::ErrorObjectRef::SyntaxError;
} else if (string == "RangeError") {
code = Escargot::ErrorObjectRef::RangeError;
} else if (string == "URIError") {
code = Escargot::ErrorObjectRef::URIError;
} else if (string == "EvalError") {
code = Escargot::ErrorObjectRef::EvalError;
} else if (string == "AggregateError") {
code = Escargot::ErrorObjectRef::AggregateError;
}

StringRef* jsMessage = createJSStringFromJava(env, message);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state,
ErrorObjectRef::Code code, StringRef* jsMessage) -> ValueRef* {
return ErrorObjectRef::create(state, code, jsMessage);
}, code, jsMessage);

assert(evaluatorResult.isSuccessful());
return createJavaObjectFromValue(env, evaluatorResult.result->asErrorObject());
}
16 changes: 16 additions & 0 deletions build/android/escargot/src/main/cpp/JNIValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ Java_com_samsung_lwe_escargot_JavaScriptValue_isPromiseObject(JNIEnv* env, jobje
return unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->isPromiseObject();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_isErrorObject(JNIEnv* env, jobject thiz)
{
return unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->isErrorObject();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_asBoolean(JNIEnv* env, jobject thiz)
Expand Down Expand Up @@ -256,6 +263,15 @@ Java_com_samsung_lwe_escargot_JavaScriptValue_asScriptPromiseObject(JNIEnv* env,
return thiz;
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_asScriptErrorObject(JNIEnv* env, jobject thiz)
{
ValueRef* ref = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz);
THROW_CAST_EXCEPTION_IF_NEEDS(env, ref, ErrorObject);
return thiz;
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptValue_toString(JNIEnv* env, jobject thiz, jobject context)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.samsung.lwe.escargot;

public class JavaScriptErrorObject extends JavaScriptObject {
protected JavaScriptErrorObject(long nativePointer)
{
super(nativePointer);
}

enum ErrorKind {
None,
ReferenceError,
TypeError,
SyntaxError,
RangeError,
URIError,
EvalError,
AggregateError
}
static public native JavaScriptErrorObject create(Context context, ErrorKind kind, String message);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ protected JavaScriptValue(long nativePointer, boolean isHeapValue)
native public boolean isArrayObject();
native public boolean isFunctionObject();
native public boolean isPromiseObject();
native public boolean isErrorObject();

native public boolean asBoolean();
native public int asInt32();
Expand All @@ -46,6 +47,7 @@ protected JavaScriptValue(long nativePointer, boolean isHeapValue)
native public JavaScriptArrayObject asScriptArrayObject();
native public JavaScriptFunctionObject asScriptFunctionObject();
native public JavaScriptPromiseObject asScriptPromiseObject();
native public JavaScriptErrorObject asScriptErrorObject();

native public Optional<JavaScriptString> toString(Context context);
native public Optional<Boolean> toBoolean(Context context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,9 @@ public void pumpEventsFromThreadIfNeeds(boolean executePendingJavaScriptJobs)
}
}

m_vmInstance.executeEveryPendingJobIfExists();
if (executePendingJavaScriptJobs) {
m_vmInstance.executeEveryPendingJobIfExists();
}
}

/**
Expand Down

0 comments on commit 2ecb52c

Please sign in to comment.