diff --git a/build/android/.gitignore b/build/android/.gitignore index aa724b770..050d01186 100644 --- a/build/android/.gitignore +++ b/build/android/.gitignore @@ -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 diff --git a/build/android/escargot/src/androidTest/java/com/samsung/lwe/escargot/EscargotTest.java b/build/android/escargot/src/androidTest/java/com/samsung/lwe/escargot/EscargotTest.java index b8554619b..f4fdef571 100644 --- a/build/android/escargot/src/androidTest/java/com/samsung/lwe/escargot/EscargotTest.java +++ b/build/android/escargot/src/androidTest/java/com/samsung/lwe/escargot/EscargotTest.java @@ -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 callback(Context context, JavaScriptValue receiverValue, JavaScriptValue[] arguments) { @@ -1046,6 +1047,7 @@ public Optional 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); @@ -1082,6 +1084,7 @@ public Optional 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); @@ -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(); + } } \ No newline at end of file diff --git a/build/android/escargot/src/main/cpp/EscargotJNI.cpp b/build/android/escargot/src/main/cpp/EscargotJNI.cpp index f23a29920..91f2531ea 100644 --- a/build/android/escargot/src/main/cpp/EscargotJNI.cpp +++ b/build/android/escargot/src/main/cpp/EscargotJNI.cpp @@ -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(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); } @@ -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 buf; diff --git a/build/android/escargot/src/main/cpp/EscargotJNI.h b/build/android/escargot/src/main/cpp/EscargotJNI.h index aeb832e30..e73eb1a3c 100644 --- a/build/android/escargot/src/main/cpp/EscargotJNI.h +++ b/build/android/escargot/src/main/cpp/EscargotJNI.h @@ -91,6 +91,7 @@ OptionalRef 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); diff --git a/build/android/escargot/src/main/cpp/JNIErrorObject.cpp b/build/android/escargot/src/main/cpp/JNIErrorObject.cpp new file mode 100644 index 000000000..576ece015 --- /dev/null +++ b/build/android/escargot/src/main/cpp/JNIErrorObject.cpp @@ -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(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()); +} \ No newline at end of file diff --git a/build/android/escargot/src/main/cpp/JNIValue.cpp b/build/android/escargot/src/main/cpp/JNIValue.cpp index a2784c58a..072920301 100644 --- a/build/android/escargot/src/main/cpp/JNIValue.cpp +++ b/build/android/escargot/src/main/cpp/JNIValue.cpp @@ -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) @@ -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) diff --git a/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptErrorObject.java b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptErrorObject.java new file mode 100644 index 000000000..8b63b77b1 --- /dev/null +++ b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptErrorObject.java @@ -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); +} diff --git a/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptValue.java b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptValue.java index 6dfa69a5a..906957c03 100644 --- a/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptValue.java +++ b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/JavaScriptValue.java @@ -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(); @@ -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 toString(Context context); native public Optional toBoolean(Context context); diff --git a/build/android/escargot/src/main/java/com/samsung/lwe/escargot/util/MultiThreadExecutor.java b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/util/MultiThreadExecutor.java index c383f1a81..413e7e64f 100644 --- a/build/android/escargot/src/main/java/com/samsung/lwe/escargot/util/MultiThreadExecutor.java +++ b/build/android/escargot/src/main/java/com/samsung/lwe/escargot/util/MultiThreadExecutor.java @@ -224,7 +224,9 @@ public void pumpEventsFromThreadIfNeeds(boolean executePendingJavaScriptJobs) } } - m_vmInstance.executeEveryPendingJobIfExists(); + if (executePendingJavaScriptJobs) { + m_vmInstance.executeEveryPendingJobIfExists(); + } } /**