Skip to content

Commit

Permalink
Compute stacktrace when creating ErrorObject
Browse files Browse the repository at this point in the history
Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 committed Nov 8, 2023
1 parent e706ea6 commit ebf3373
Show file tree
Hide file tree
Showing 24 changed files with 372 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1837,12 +1837,15 @@ public Optional<JavaScriptValue> callback(Context context, Optional<JavaScriptVa
return null;
}
});
Evaluator.evalScript(context, "Native.throwsException()", "");
ret = Evaluator.evalScript(context, "Native.throwsException()", "");
ret = Evaluator.evalScript(context, "Native.throwsException()", "test.js");
assertFalse(ret.isPresent());
assertTrue(context.exceptionWasThrown());
JavaScriptErrorObject err = context.lastThrownException().get().asScriptErrorObject();
assertTrue(err.extraData().get() instanceof RuntimeException);
assertEquals(err.stack(context).get().toJavaString(),
"at test.js:1:1\n" +
"Native.throwsException(\n" +
"^");

ArrayList<Object> thenCalled = new ArrayList<>();
JavaScriptPromiseObject promise = JavaScriptPromiseObject.create(context);
Expand Down
1 change: 1 addition & 0 deletions build/android/escargot/src/main/cpp/EscargotJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

JavaVM* g_jvm;
size_t g_nonPointerValueLast = reinterpret_cast<size_t>(ValueRef::createUndefined());
thread_local std::vector<ExecutionStateRef*> ExecutionStateRefTracker::g_lastExecutionStateVector;

jobject createJavaValueObject(JNIEnv* env, jclass clazz, ValueRef* value)
{
Expand Down
38 changes: 38 additions & 0 deletions build/android/escargot/src/main/cpp/EscargotJNI.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#include <jni.h>
#include <EscargotPublic.h>
#include <vector>
#include <set>
#include <cassert>

using namespace Escargot;
Expand Down Expand Up @@ -144,4 +146,40 @@ PersistentRefHolder<NativeType>* getPersistentPointerFromJava(JNIEnv *env, jclas
return pVMRef;
}

class ExecutionStateRefTracker {
public:
ExecutionStateRefTracker(ExecutionStateRef* newValue)
{
g_lastExecutionStateVector.push_back(newValue);
}

~ExecutionStateRefTracker()
{
g_lastExecutionStateVector.pop_back();
}
private:
friend class ScriptEvaluator;
static thread_local std::vector<ExecutionStateRef*> g_lastExecutionStateVector;
};

class ScriptEvaluator {
public:
template <typename... Args, typename F>
static Evaluator::EvaluatorResult execute(ContextRef* ctx, F&& closure, Args... args)
{
typedef ValueRef* (*Closure)(ExecutionStateRef * state, Args...);
if (ExecutionStateRefTracker::g_lastExecutionStateVector.size()) {
return Evaluator::execute(ExecutionStateRefTracker::g_lastExecutionStateVector.back(), [](ExecutionStateRef * state, Closure closure, Args... args) -> ValueRef* {
ExecutionStateRefTracker tracker(state);
return closure(state, args...);
}, Closure(closure), args...);
} else {
return Evaluator::execute(ctx, [](ExecutionStateRef * state, Closure closure, Args... args) -> ValueRef* {
ExecutionStateRefTracker tracker(state);
return closure(state, args...);
}, Closure(closure), args...);
}
}
};

#endif //ESCARGOT_ANDROID_ESCARGOTJNI_H
6 changes: 3 additions & 3 deletions build/android/escargot/src/main/cpp/JNIArrayObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Java_com_samsung_lwe_escargot_JavaScriptArrayObject_create(JNIEnv* env, jclass c
THROW_NPE_RETURN_NULL(context, "Context");

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

Expand All @@ -45,7 +45,7 @@ Java_com_samsung_lwe_escargot_JavaScriptArrayObject_length(JNIEnv* env, jobject
ArrayObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asArrayObject();

int64_t length = 0;
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ArrayObjectRef* thisValueRef, int64_t* pLength) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ArrayObjectRef* thisValueRef, int64_t* pLength) -> ValueRef* {
*pLength = static_cast<int64_t>(thisValueRef->length(state));
return ValueRef::createUndefined();
}, thisValueRef, &length);
Expand All @@ -63,7 +63,7 @@ Java_com_samsung_lwe_escargot_JavaScriptArrayObject_setLength(JNIEnv* env, jobje
auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ArrayObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asArrayObject();

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ArrayObjectRef* thisValueRef, jlong pLength) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ArrayObjectRef* thisValueRef, jlong pLength) -> ValueRef* {
if (pLength >= 0) {
thisValueRef->setLength(state, static_cast<uint64_t>(pLength));
} else {
Expand Down
2 changes: 1 addition & 1 deletion build/android/escargot/src/main/cpp/JNIBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Java_com_samsung_lwe_escargot_Bridge_register(JNIEnv* env, jclass clazz, jobject

adapter = env->NewGlobalRef(adapter);

auto evalResult = Evaluator::execute(contextPtr->get(),
auto evalResult = ScriptEvaluator::execute(contextPtr->get(),
[](ExecutionStateRef* state, JNIEnv* env, jobject adapter,
StringRef* jsObjectName,
StringRef* jsPropertyName) -> ValueRef* {
Expand Down
19 changes: 18 additions & 1 deletion build/android/escargot/src/main/cpp/JNIErrorObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,28 @@ Java_com_samsung_lwe_escargot_JavaScriptErrorObject_create(JNIEnv* env, jclass c
StringRef* jsMessage = createJSStringFromJava(env, message);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state,
auto evaluatorResult = ScriptEvaluator::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());
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_samsung_lwe_escargot_JavaScriptErrorObject_stack(JNIEnv* env, jobject thiz,
jobject context)
{
THROW_NPE_RETURN_NULL(context, "Context");

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ErrorObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asErrorObject();

auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ErrorObjectRef* thisValueRef) -> ValueRef* {
return thisValueRef->getOwnProperty(state, StringRef::createFromASCII("stack"))->toString(state);
}, thisValueRef);

return createOptionalValueFromEvaluatorJavaScriptValueResult(env, context, contextRef->get(), evaluatorResult);
}
2 changes: 1 addition & 1 deletion build/android/escargot/src/main/cpp/JNIEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static Evaluator::EvaluatorResult evalScript(ContextRef* context, StringRef* sou
return evalResult;
}

auto evalResult = Evaluator::execute(context, [](ExecutionStateRef* state, ScriptRef* script) -> ValueRef* {
auto evalResult = ScriptEvaluator::execute(context, [](ExecutionStateRef* state, ScriptRef* script) -> ValueRef* {
return script->execute(state);
},
scriptInitializeResult.script.get());
Expand Down
2 changes: 1 addition & 1 deletion build/android/escargot/src/main/cpp/JNIFunctionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Java_com_samsung_lwe_escargot_JavaScriptJavaCallbackFunctionObject_create(JNIEnv
argumentCount,
isConstructor);

auto evaluatorResult = Evaluator::execute(contextRef->get(),
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(),
[](ExecutionStateRef* state, FunctionObjectRef::NativeFunctionInfo info) -> ValueRef* {
return FunctionObjectRef::create(state, info);
}, info);
Expand Down
6 changes: 3 additions & 3 deletions build/android/escargot/src/main/cpp/JNIGlobalObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Java_com_samsung_lwe_escargot_JavaScriptGlobalObject_jsonStringify(JNIEnv* env,
auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ValueRef* inputValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(input), input);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, GlobalObjectRef* globalObject, ValueRef* inputValueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, GlobalObjectRef* globalObject, ValueRef* inputValueRef) -> ValueRef* {
return globalObject->jsonStringify()->call(state, globalObject->json(), 1, &inputValueRef);
}, globalObjectRef->get(), inputValueRef);

Expand All @@ -51,7 +51,7 @@ Java_com_samsung_lwe_escargot_JavaScriptGlobalObject_jsonParse(JNIEnv* env, jobj
auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ValueRef* inputValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(input), input);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, GlobalObjectRef* globalObject, ValueRef* inputValueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, GlobalObjectRef* globalObject, ValueRef* inputValueRef) -> ValueRef* {
return globalObject->jsonParse()->call(state, globalObject->json(), 1, &inputValueRef);
}, globalObjectRef->get(), inputValueRef);

Expand All @@ -69,7 +69,7 @@ static jobject callPromiseBuiltinFunction(JNIEnv* env, jobject thiz, jobject con
auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
ValueRef* iterableValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(iterable), iterable);

auto evaluatorResult = Evaluator::execute(contextRef->get(), closure, globalObjectRef->get(), iterableValueRef);
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), closure, globalObjectRef->get(), iterableValueRef);

return createOptionalValueFromEvaluatorJavaScriptValueResult(env, context, contextRef->get(),
evaluatorResult);
Expand Down
10 changes: 5 additions & 5 deletions build/android/escargot/src/main/cpp/JNIObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_create(JNIEnv* env, jclass clazz,
THROW_NPE_RETURN_NULL(context, "Context");

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

Expand All @@ -46,7 +46,7 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_get(JNIEnv* env, jobject thiz, jo
ObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asObject();
ValueRef* propertyNameValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(propertyName), propertyName);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef) -> ValueRef* {
return thisValueRef->get(state, propertyNameValueRef);
}, thisValueRef, propertyNameValueRef);

Expand All @@ -68,7 +68,7 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_set(JNIEnv* env, jobject thiz, jo
ValueRef* propertyNameValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(propertyName), propertyName);
ValueRef* valueRef = unwrapValueRefFromValue(env, env->GetObjectClass(value), value);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef, ValueRef* valueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef, ValueRef* valueRef) -> ValueRef* {
return ValueRef::create(thisValueRef->set(state, propertyNameValueRef, valueRef));
}, thisValueRef, propertyNameValueRef, valueRef);

Expand All @@ -95,7 +95,7 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_defineDataProperty(JNIEnv* env, j
ValueRef* propertyNameValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(propertyName), propertyName);
ValueRef* valueRef = unwrapValueRefFromValue(env, env->GetObjectClass(value), value);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef, ValueRef* valueRef,
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef, ValueRef* valueRef,
jboolean isWritable,
jboolean isEnumerable,
jboolean isConfigurable) -> ValueRef* {
Expand All @@ -119,7 +119,7 @@ Java_com_samsung_lwe_escargot_JavaScriptObject_getOwnProperty(JNIEnv* env, jobje
ObjectRef* thisValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(thiz), thiz)->asObject();
ValueRef* propertyNameValueRef = unwrapValueRefFromValue(env, env->GetObjectClass(propertyName), propertyName);

auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, ObjectRef* thisValueRef, ValueRef* propertyNameValueRef) -> ValueRef* {
return thisValueRef->getOwnProperty(state, propertyNameValueRef);
}, thisValueRef, propertyNameValueRef);

Expand Down
12 changes: 6 additions & 6 deletions build/android/escargot/src/main/cpp/JNIPromiseObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_create(JNIEnv* env, jclass
THROW_NPE_RETURN_NULL(context, "Context");

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

Expand Down Expand Up @@ -77,7 +77,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_then__Lcom_samsung_lwe_esc
ValueRef* handlerRef = unwrapValueRefFromValue(env, env->GetObjectClass(handler), handler);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* handlerRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* handlerRef) -> ValueRef* {
return promiseObject->then(state, handlerRef);
}, thisValueRef, handlerRef);

Expand All @@ -99,7 +99,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_then__Lcom_samsung_lwe_esc
ValueRef* onRejectedRef = unwrapValueRefFromValue(env, env->GetObjectClass(onRejected), onRejected);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* onFulfilledRef, ValueRef* onRejectedRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* onFulfilledRef, ValueRef* onRejectedRef) -> ValueRef* {
return promiseObject->then(state, onFulfilledRef, onRejectedRef);
}, thisValueRef, onFulfilledRef, onRejectedRef);

Expand All @@ -119,7 +119,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_catchOperation(JNIEnv* env
ValueRef* handlerRef = unwrapValueRefFromValue(env, env->GetObjectClass(handler), handler);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* handlerRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* handlerRef) -> ValueRef* {
return promiseObject->catchOperation(state, handlerRef);
}, thisValueRef, handlerRef);

Expand All @@ -138,7 +138,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_fulfill(JNIEnv* env, jobje
ValueRef* valueRef = unwrapValueRefFromValue(env, env->GetObjectClass(value), value);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* valueRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* valueRef) -> ValueRef* {
promiseObject->fulfill(state, valueRef);
return ValueRef::createUndefined();
}, thisValueRef, valueRef);
Expand All @@ -156,7 +156,7 @@ Java_com_samsung_lwe_escargot_JavaScriptPromiseObject_reject(JNIEnv* env, jobjec
ValueRef* reasonRef = unwrapValueRefFromValue(env, env->GetObjectClass(reason), reason);

auto contextRef = getPersistentPointerFromJava<ContextRef>(env, env->GetObjectClass(context), context);
auto evaluatorResult = Evaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* reasonRef) -> ValueRef* {
auto evaluatorResult = ScriptEvaluator::execute(contextRef->get(), [](ExecutionStateRef* state, PromiseObjectRef* promiseObject, ValueRef* reasonRef) -> ValueRef* {
promiseObject->reject(state, reasonRef);
return ValueRef::createUndefined();
}, thisValueRef, reasonRef);
Expand Down
Loading

0 comments on commit ebf3373

Please sign in to comment.