From db4fa836a5b836b15e7e85d4ab397ea8ec8708f9 Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Fri, 11 Oct 2024 15:57:12 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=B9=E6=B3=95:=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=BD=BF=E7=94=A8=E5=86=85=E5=AD=98=E7=9A=84?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- native/cpp/quickjs_context_jni.cpp | 9 +++++++++ .../java/com/whl/quickjs/wrapper/QuickJSContext.java | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/native/cpp/quickjs_context_jni.cpp b/native/cpp/quickjs_context_jni.cpp index 5986169..2bfa46b 100644 --- a/native/cpp/quickjs_context_jni.cpp +++ b/native/cpp/quickjs_context_jni.cpp @@ -270,4 +270,13 @@ Java_com_whl_quickjs_wrapper_QuickJSContext_getOwnPropertyNames(JNIEnv *env, job jlong context, jlong obj_value) { auto wrapper = reinterpret_cast(context); return wrapper->getOwnPropertyNames(env, thiz, obj_value); +} +extern "C" +JNIEXPORT jlong JNICALL +Java_com_whl_quickjs_wrapper_QuickJSContext_getMemoryUsedSize(JNIEnv *env, jobject thiz, + jlong runtime) { + auto *rt = reinterpret_cast(runtime); + JSMemoryUsage usage; + JS_ComputeMemoryUsage(rt, &usage); + return (jlong)usage.memory_used_size; } \ No newline at end of file diff --git a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSContext.java b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSContext.java index 588533c..ef2c3d3 100644 --- a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSContext.java +++ b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSContext.java @@ -125,6 +125,11 @@ public void setMemoryLimit(int memoryLimitSize) { setMemoryLimit(runtime, memoryLimitSize); } + // Return the byte size. + public long getMemoryUsedSize() { + return getMemoryUsedSize(runtime); + } + public void dumpMemoryUsage(File target) { if (target == null || !target.exists()) { return; @@ -578,6 +583,7 @@ public Object getOwnPropertyNames(JSObject object) { private native void setMemoryLimit(long runtime, int size); private native void dumpMemoryUsage(long runtime, String fileName); private native void dumpObjects(long runtime, String fileName); + private native long getMemoryUsedSize(long runtime); // context private native long createContext(long runtime); From 90df7d9166e0f06e641278fc5a359db03252c18a Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 17 Oct 2024 19:07:05 +0800 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20ArrayBuffer=20?= =?UTF-8?q?=E5=92=8C=20byte=20=E7=B1=BB=E5=9E=8B=E4=BA=92=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- native/cpp/quickjs_wrapper.cpp | 28 ++++++++++++++++++- native/cpp/quickjs_wrapper.h | 1 + .../com/whl/quickjs/wrapper/QuickJSTest.java | 17 +++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/native/cpp/quickjs_wrapper.cpp b/native/cpp/quickjs_wrapper.cpp index e480598..0e37d4e 100644 --- a/native/cpp/quickjs_wrapper.cpp +++ b/native/cpp/quickjs_wrapper.cpp @@ -23,6 +23,13 @@ static string getJavaName(JNIEnv* env, jobject javaClass) { return str; } +// quickjs 没有提供 JS_IsArrayBuffer 方法,这里通过取巧的方式来实现,后续可以替换掉 +static bool JS_IsArrayBuffer(JSValue value) { + // quickjs 里的 ArrayBuffer 对应的类型枚举值 + int8_t JS_CLASS_ARRAY_BUFFER = 19; + return JS_GetClassID(value) == JS_CLASS_ARRAY_BUFFER; +} + static void tryToTriggerOnError(JSContext *ctx, JSValueConst *error) { JSValue global = JS_GetGlobalObject(ctx); JSValue onerror = JS_GetPropertyStr(ctx, global, "onError"); @@ -333,6 +340,7 @@ QuickJSWrapper::QuickJSWrapper(JNIEnv *env, jobject thiz, JSRuntime *rt) { quickjsContextClass = (jclass)(jniEnv->NewGlobalRef(jniEnv->FindClass("com/whl/quickjs/wrapper/QuickJSContext"))); moduleLoaderClass = (jclass)(jniEnv->NewGlobalRef(jniEnv->FindClass("com/whl/quickjs/wrapper/ModuleLoader"))); creatorClass = (jclass)(jniEnv->NewGlobalRef(jniEnv->FindClass("com/whl/quickjs/wrapper/JSObjectCreator"))); + byteArrayClass = (jclass) jniEnv->NewGlobalRef(env->FindClass("[B")); booleanValueOf = jniEnv->GetStaticMethodID(booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;"); integerValueOf = jniEnv->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;"); @@ -376,6 +384,7 @@ QuickJSWrapper::~QuickJSWrapper() { jniEnv->DeleteGlobalRef(moduleLoaderClass); jniEnv->DeleteGlobalRef(quickjsContextClass); jniEnv->DeleteGlobalRef(creatorClass); + jniEnv->DeleteGlobalRef(byteArrayClass); } jobject QuickJSWrapper::toJavaObject(JNIEnv *env, jobject thiz, JSValueConst& this_obj, JSValueConst& value) const{ @@ -436,6 +445,16 @@ jobject QuickJSWrapper::toJavaObject(JNIEnv *env, jobject thiz, JSValueConst& th result = env->CallObjectMethod(creatorObj, newFunctionM, thiz, value_ptr, obj_ptr); } else if (JS_IsArray(context, value)) { result = env->CallObjectMethod(creatorObj, newArrayM, thiz, value_ptr); + } else if (JS_IsArrayBuffer(value)) { + size_t byteLength = 0; + uint8_t *buffer = JS_GetArrayBuffer(context, &byteLength, value); + jbyteArray byteArray = env->NewByteArray(byteLength); + void *elementsPtr = env->GetPrimitiveArrayCritical(byteArray, nullptr); + jbyte *elements = reinterpret_cast(elementsPtr); + memcpy(elements, buffer, byteLength); + result = byteArray; + JS_FreeValue(context, value); + env->ReleasePrimitiveArrayCritical(byteArray, elements, 0); } else { result = env->CallObjectMethod(creatorObj, newObjectM, thiz, value_ptr); } @@ -514,7 +533,8 @@ jobject QuickJSWrapper::call(JNIEnv *env, jobject thiz, jlong func, jlong this_o // 基础类型(例如 string )和 Java callback 类型需要使用完 free. if (env->IsInstanceOf(arg, stringClass) || env->IsInstanceOf(arg, doubleClass) || env->IsInstanceOf(arg, integerClass) || env->IsInstanceOf(arg, longClass) || - env->IsInstanceOf(arg, booleanClass) || env->IsInstanceOf(arg, jsCallFunctionClass)) { + env->IsInstanceOf(arg, booleanClass) || env->IsInstanceOf(arg, jsCallFunctionClass) + || env->IsInstanceOf(arg, byteArrayClass)) { freeArguments.push_back(jsArg); } @@ -676,6 +696,12 @@ JSValue QuickJSWrapper::toJSValue(JNIEnv *env, jobject thiz, jobject value) cons } } else if (env->IsInstanceOf(value, booleanClass)) { result = JS_NewBool(context, env->CallBooleanMethod(value, booleanGetValue)); + } else if (env->IsInstanceOf(value, byteArrayClass)) { + jbyteArray bytes = static_cast(value); + jbyte* byteData = env->GetByteArrayElements(bytes, nullptr); + jsize length = env->GetArrayLength(bytes); + result = JS_NewArrayBufferCopy(context, reinterpret_cast(byteData), length); + env->ReleaseByteArrayElements(bytes, byteData, JNI_ABORT); } else if (env->IsInstanceOf(value, jsObjectClass)) { result = JS_MKPTR(JS_TAG_OBJECT, reinterpret_cast(env->CallLongMethod(value, jsObjectGetValue))); } else if (env->IsInstanceOf(value, jsCallFunctionClass)) { diff --git a/native/cpp/quickjs_wrapper.h b/native/cpp/quickjs_wrapper.h index 57cc0a5..2ba22f9 100644 --- a/native/cpp/quickjs_wrapper.h +++ b/native/cpp/quickjs_wrapper.h @@ -42,6 +42,7 @@ class QuickJSWrapper { jclass quickjsContextClass; jclass moduleLoaderClass; jclass creatorClass; + jclass byteArrayClass; JSValue ownPropertyNames; jmethodID booleanValueOf; diff --git a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java index 2192764..a9f630b 100644 --- a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java +++ b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java @@ -1236,4 +1236,21 @@ public void testObjectLeakDetection() { context.destroy(); } + @Test + public void testArrayBytes() { + QuickJSContext context = createContext(); + byte[] bytes = "test测试".getBytes(); + byte[] buffer = (byte[]) context.evaluate("new Uint8Array([116, 101, 115, 116, 230, 181, 139, 232, 175, 149]).buffer"); + assertArrayEquals(bytes, buffer); + context.destroy(); + } + + @Test + public void testArrayBytes1() { + QuickJSContext context = createContext(); + JSFunction bufferTest = (JSFunction) context.evaluate("const bufferTest = (buffer) => { console.log(new Uint8Array(buffer)); }; bufferTest;"); + bufferTest.callVoid("test测试".getBytes()); + context.destroy(); + } + } From 30cf4656347b39e1d57b4707eb91cf131e5afac2 Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 17 Oct 2024 19:29:15 +0800 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20ArrayBuffer=20?= =?UTF-8?q?=E5=92=8C=20byte=20=E7=B1=BB=E5=9E=8B=E4=BA=92=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/com/whl/quickjs/wrapper/QuickJSTest.java | 7 ++++++- .../main/java/com/whl/quickjs/wrapper/JSObject.java | 2 ++ .../java/com/whl/quickjs/wrapper/QuickJSObject.java | 11 +++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2172bc7..6f792e5 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ context.setConsole(your console implementation.); - `int` - `long` - `double` +- `byte[]` <=> ArrayBuffer - `String` - `null` diff --git a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java index a9f630b..8b3c2f0 100644 --- a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java +++ b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java @@ -1242,13 +1242,18 @@ public void testArrayBytes() { byte[] bytes = "test测试".getBytes(); byte[] buffer = (byte[]) context.evaluate("new Uint8Array([116, 101, 115, 116, 230, 181, 139, 232, 175, 149]).buffer"); assertArrayEquals(bytes, buffer); + + context.getGlobalObject().setProperty("testBuffer", bytes); + byte[] testBuffers = context.getGlobalObject().getBytes("testBuffer"); + assertArrayEquals(testBuffers, buffer); + context.destroy(); } @Test public void testArrayBytes1() { QuickJSContext context = createContext(); - JSFunction bufferTest = (JSFunction) context.evaluate("const bufferTest = (buffer) => { console.log(new Uint8Array(buffer)); }; bufferTest;"); + JSFunction bufferTest = (JSFunction) context.evaluate("const bufferTest = (buffer) => { if(new Uint8Array(buffer)[0] !== 116) { throw Error('failed, not equal'); }; }; bufferTest;"); bufferTest.callVoid("test测试".getBytes()); context.destroy(); } diff --git a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/JSObject.java b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/JSObject.java index b34caa5..d36f7de 100644 --- a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/JSObject.java +++ b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/JSObject.java @@ -14,6 +14,7 @@ public interface JSObject { void setProperty(String name, JSObject value); void setProperty(String name, boolean value); void setProperty(String name, double value); + void setProperty(String name, byte[] value); void setProperty(String name, JSCallFunction value); void setProperty(String name, Class clazz); long getPointer(); @@ -32,6 +33,7 @@ public interface JSObject { Double getDoubleProperty(String name); Double getDouble(String name); Long getLong(String name); + byte[] getBytes(String name); @Deprecated JSObject getJSObjectProperty(String name); JSObject getJSObject(String name); diff --git a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSObject.java b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSObject.java index 0294de6..f3fe291 100644 --- a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSObject.java +++ b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSObject.java @@ -84,6 +84,11 @@ public void setProperty(String name, double value) { setPropertyObject(name, value); } + @Override + public void setProperty(String name, byte[] value) { + setPropertyObject(name, value); + } + @Override public void setProperty(String name, JSCallFunction value) { setPropertyObject(name, value); @@ -176,6 +181,12 @@ public Long getLong(String name) { return value instanceof Long ? (Long) value : null; } + @Override + public byte[] getBytes(String name) { + Object value = getProperty(name); + return value instanceof byte[] ? (byte[]) value : null; + } + @Override public JSObject getJSObjectProperty(String name) { return getJSObject(name); From 6a3c2741511f3dffeef4ed5bc8125d34d4cb590e Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Tue, 22 Oct 2024 11:14:17 +0800 Subject: [PATCH 4/9] update README.md --- README.md | 58 +++++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 6f792e5..a58116b 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@ QuickJS wrapper for Android/JVM. - JavaScript exception handler - Compile bytecode - Supports converting JS object types to Java HashMap. - -Experimental Features Stability not guaranteed. - ESModule (import, export) ## Download @@ -85,20 +83,14 @@ QuickJSLoader.init(); ```Java QuickJSContext context = QuickJSContext.create(); -``` -### Destroy QuickJSContext +// evaluating JavaScript +context.evaluate("var a = 1 + 2;"); -```Java +// destroy QuickJSContext context.destroy(); ``` -### Evaluating JavaScript - -```Java -context.evaluate("var a = 1 + 2;"); -``` - ### Console Support ```Java context.setConsole(your console implementation.); @@ -107,29 +99,27 @@ context.setConsole(your console implementation.); ### Supported Types #### Java and JavaScript can directly convert to each other for the following basic types -- `boolean` -- `int` -- `long` -- `double` -- `byte[]` <=> ArrayBuffer -- `String` -- `null` - -#### Mutual conversion of JS object types -- `JSObject` represents a JavaScript object -- `JSFunction` represents a JavaScript function -- `JSArray` represents a JavaScript Array - -#### About Long type -There is no Long type in JavaScript, the conversion of Long type is special. - -- Java --> JavaScript - - The Long value <= Number.MAX_SAFE_INTEGER, will be convert to Number type. - - The Long value > Number.MAX_SAFE_INTEGER, will be convert to BigInt type. - - Number.MIN_SAFE_INTEGER is the same to above. - -- JavaScript --> Java - - Number(Int64) or BigInt --> Long type +| JavaScript | Java | +|------------|-----------------| +| null | null | +| undefined | null | +| boolean | Boolean | +| Number | Long/Int/Double | +| string | String | +| Array | JSArray | +| object | JSObject | +| Function | JSFunction | + +Since JavaScript doesn't have a `long` type, additional information about `long`: + +Java --> JavaScript + - The Long value <= Number.MAX_SAFE_INTEGER, will be convert to Number type. + - The Long value > Number.MAX_SAFE_INTEGER, will be convert to BigInt type. + - Number.MIN_SAFE_INTEGER is the same to above. + +JavaScript --> Java + - Number(Int64) or BigInt --> Long type + ### Set Property Java From b332652fc17b62e95e927c360b76bc7797629cea Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Tue, 5 Nov 2024 15:59:45 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/whl/quickjs/wrapper/QuickJSFunction.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSFunction.java b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSFunction.java index f48e235..935b29b 100644 --- a/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSFunction.java +++ b/wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSFunction.java @@ -12,12 +12,12 @@ public class QuickJSFunction extends QuickJSObject implements JSFunction { * 函数执行状态 */ enum Status { - NOT_STARTED, - IN_PROGRESS, - COMPLETED + NOT_CALLED, + CALLING, + CALLED } private int stashTimes = 0; - private Status currentStatus = Status.NOT_STARTED; + private Status currentStatus = Status.NOT_CALLED; private final long thisPointer; @@ -30,7 +30,7 @@ public QuickJSFunction(QuickJSContext context, long pointer, long thisPointer) { public void release() { // call 函数未执行完,触发了 release 操作,会导致 quickjs 野指针异常, // 这里暂存一下,待函数执行完,才执行 release。 - if (currentStatus == Status.IN_PROGRESS) { + if (currentStatus == Status.CALLING) { stashTimes++; return; } @@ -41,9 +41,9 @@ public void release() { public Object call(Object... args) { checkRefCountIsZero(); - currentStatus = Status.IN_PROGRESS; + currentStatus = Status.CALLING; Object ret = getContext().call(this, thisPointer, args); - currentStatus = Status.COMPLETED; + currentStatus = Status.CALLED; if (stashTimes > 0) { // 如果有暂存,这里需要恢复下 release 操作 From a27345d901060ba243a7b40fbcf03e303df7bd06 Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 14 Nov 2024 09:59:39 +0800 Subject: [PATCH 6/9] update test case --- .../androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java index 8b3c2f0..72ae1fd 100644 --- a/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java +++ b/wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java @@ -1240,7 +1240,7 @@ public void testObjectLeakDetection() { public void testArrayBytes() { QuickJSContext context = createContext(); byte[] bytes = "test测试".getBytes(); - byte[] buffer = (byte[]) context.evaluate("new Uint8Array([116, 101, 115, 116, 230, 181, 139, 232, 175, 149]).buffer"); + byte[] buffer = (byte[]) context.evaluate("new Int8Array([116, 101, 115, 116, -26, -75, -117, -24, -81, -107]).buffer"); assertArrayEquals(bytes, buffer); context.getGlobalObject().setProperty("testBuffer", bytes); @@ -1253,7 +1253,7 @@ public void testArrayBytes() { @Test public void testArrayBytes1() { QuickJSContext context = createContext(); - JSFunction bufferTest = (JSFunction) context.evaluate("const bufferTest = (buffer) => { if(new Uint8Array(buffer)[0] !== 116) { throw Error('failed, not equal'); }; }; bufferTest;"); + JSFunction bufferTest = (JSFunction) context.evaluate("const bufferTest = (buffer) => { if(new Int8Array(buffer)[0] !== 116) { throw Error('failed, not equal'); }; }; bufferTest;"); bufferTest.callVoid("test测试".getBytes()); context.destroy(); } From 926182abea95abf28957e0d910a3b5cc9f06825e Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 14 Nov 2024 10:09:15 +0800 Subject: [PATCH 7/9] update README --- README.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a58116b..a8ef5be 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ QuickJS wrapper for Android/JVM. - Supports converting JS object types to Java HashMap. - ESModule (import, export) +Experimental Features Stability not guaranteed. +- Supports ArrayBuffer to a byte array type. + ## Download [![Maven Central](https://img.shields.io/maven-central/v/wang.harlon.quickjs/wrapper-android.svg?label=Maven%20Central&color=blue)](https://search.maven.org/search?q=g:%22wang.harlon.quickjs%22%20AND%20a:%22wrapper-android%22) @@ -99,16 +102,17 @@ context.setConsole(your console implementation.); ### Supported Types #### Java and JavaScript can directly convert to each other for the following basic types -| JavaScript | Java | -|------------|-----------------| -| null | null | -| undefined | null | -| boolean | Boolean | -| Number | Long/Int/Double | -| string | String | -| Array | JSArray | -| object | JSObject | -| Function | JSFunction | +| JavaScript | Java | +|-------------|-------------------| +| null | null | +| undefined | null | +| boolean | Boolean | +| Number | Long/Int/Double | +| string | String | +| Array | JSArray | +| object | JSObject | +| Function | JSFunction | +| ArrayBuffer | byte[](Deep copy) | Since JavaScript doesn't have a `long` type, additional information about `long`: From f2573ae9ccab62d07bb2a326ab07711813abd035 Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 14 Nov 2024 10:11:50 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BC=98=E5=8C=96:=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- native/cpp/quickjs_wrapper.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/native/cpp/quickjs_wrapper.cpp b/native/cpp/quickjs_wrapper.cpp index 0e37d4e..7e0c0c9 100644 --- a/native/cpp/quickjs_wrapper.cpp +++ b/native/cpp/quickjs_wrapper.cpp @@ -238,6 +238,12 @@ jsModuleLoaderFunc(JSContext *ctx, const char *module_name, void *opaque) { int scriptLen = env->GetStringUTFLength((jstring) result); JSValue func_val = JS_Eval(ctx, script, scriptLen, module_name, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + if (JS_IsException(func_val)) { + JS_FreeValue(ctx, func_val); + throwJSException(env, ctx); + return (JSModuleDef *) JS_VALUE_GET_PTR(JS_EXCEPTION); + } + m = JS_VALUE_GET_PTR(func_val); JS_FreeValue(ctx, func_val); } From 0cb3b5b20a11e94495240c0173e889e50b4ffcea Mon Sep 17 00:00:00 2001 From: HarlonWang <81813780@qq.com> Date: Thu, 14 Nov 2024 10:14:43 +0800 Subject: [PATCH 9/9] release version to 2.4.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ac1377..0588f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 2.4.0 *(2024-11-14)* +- 新增方法: 获取使用内存的大小信息(getMemoryUsedSize) +- 支持 ArrayBuffer 转为 Byte 数组(深拷贝,对性能有一些影响) + ## 2.2.1 *(2024-09-29)* - JSObject 增加 toMap 方法,支持转 HashMap 类型