From 6470acbe7854df2f733a55c64c9db43f293928c5 Mon Sep 17 00:00:00 2001 From: Andrey Rylov Date: Thu, 13 Apr 2023 19:45:54 +0400 Subject: [PATCH 1/3] add max stack size to java wrapper --- library/src/main/c/quickjs-jni.c | 12 ++++++++++++ .../java/com/hippo/quickjs/android/JSRuntime.java | 15 +++++++++++++++ .../java/com/hippo/quickjs/android/QuickJS.java | 1 + 3 files changed, 28 insertions(+) diff --git a/library/src/main/c/quickjs-jni.c b/library/src/main/c/quickjs-jni.c index 2f45eff..6b193a3 100644 --- a/library/src/main/c/quickjs-jni.c +++ b/library/src/main/c/quickjs-jni.c @@ -47,6 +47,18 @@ Java_com_hippo_quickjs_android_QuickJS_setRuntimeMallocLimit( JS_SetMemoryLimit(qj_rt->rt, (size_t) malloc_limit); } +JNIEXPORT void JNICALL +Java_com_hippo_quickjs_android_QuickJS_setRuntimeMaxStackSize( + JNIEnv *env, + jclass __unused clazz, + jlong runtime, + jint stack_size +) { + QJRuntime *qj_rt = (QJRuntime *) runtime; + CHECK_NULL(env, qj_rt, MSG_NULL_JS_RUNTIME); + JS_SetMaxStackSize(qj_rt->rt, (size_t) stack_size); +} + static int on_interrupt(JSRuntime __unused *rt, void *opaque) { int result = 0; diff --git a/library/src/main/java/com/hippo/quickjs/android/JSRuntime.java b/library/src/main/java/com/hippo/quickjs/android/JSRuntime.java index 7bf81d2..015ff52 100644 --- a/library/src/main/java/com/hippo/quickjs/android/JSRuntime.java +++ b/library/src/main/java/com/hippo/quickjs/android/JSRuntime.java @@ -59,6 +59,21 @@ public synchronized void setMallocLimit(int mallocLimit) { QuickJS.setRuntimeMallocLimit(pointer, mallocLimit); } + /** + * Set max stack size for this JSRuntime. + * Only positive number and {@code 0} are accepted. + * {@code 0} for no stack size check. + */ + public synchronized void setMaxStackSize(int stackSize) { + checkClosed(); + + if (stackSize < 0) { + throw new IllegalArgumentException("Only positive number and 0 are accepted as max stack size"); + } + + QuickJS.setRuntimeMaxStackSize(pointer, stackSize); + } + /** * Set the InterruptHandler for this JSRuntime. * {@link InterruptHandler#onInterrupt()} is called every 10000 js instructions. diff --git a/library/src/main/java/com/hippo/quickjs/android/QuickJS.java b/library/src/main/java/com/hippo/quickjs/android/QuickJS.java index 7b68dd7..af551a2 100644 --- a/library/src/main/java/com/hippo/quickjs/android/QuickJS.java +++ b/library/src/main/java/com/hippo/quickjs/android/QuickJS.java @@ -109,6 +109,7 @@ public QuickJS build() { static native long createRuntime(); static native void setRuntimeMallocLimit(long runtime, int mallocLimit); + static native void setRuntimeMaxStackSize(long runtime, int stackSize); static native void setRuntimeInterruptHandler(long runtime, JSRuntime.InterruptHandler interruptHandler); static native void destroyRuntime(long runtime); From 45328d290aec9424eda476d2a1c21c6cb63641c3 Mon Sep 17 00:00:00 2001 From: Andrey Rylov Date: Wed, 17 Sep 2025 18:44:10 +0400 Subject: [PATCH 2/3] update ndk and alignment --- android-test/CMakeLists.txt | 5 - android-test/build.gradle | 109 ------- android-test/src/main/AndroidManifest.xml | 49 --- .../com/hippo/quickjs/android/test/App.kt | 27 -- .../com/hippo/quickjs/android/test/LogView.kt | 131 -------- .../quickjs/android/test/MessagePrinter.kt | 25 -- .../quickjs/android/test/MessageQueue.kt | 57 ---- .../quickjs/android/test/TestActivity.kt | 56 ---- .../com/hippo/quickjs/android/test/Tester.kt | 282 ------------------ android-test/src/main/res/xml/file_paths.xml | 20 -- build.gradle | 46 +-- gradle/wrapper/gradle-wrapper.properties | 4 +- library/build.gradle | 42 +-- settings.gradle | 36 +-- 14 files changed, 39 insertions(+), 850 deletions(-) delete mode 100644 android-test/CMakeLists.txt delete mode 100644 android-test/build.gradle delete mode 100644 android-test/src/main/AndroidManifest.xml delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/App.kt delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/LogView.kt delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/MessagePrinter.kt delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/MessageQueue.kt delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/TestActivity.kt delete mode 100644 android-test/src/main/java/com/hippo/quickjs/android/test/Tester.kt delete mode 100644 android-test/src/main/res/xml/file_paths.xml diff --git a/android-test/CMakeLists.txt b/android-test/CMakeLists.txt deleted file mode 100644 index 05bd7fb..0000000 --- a/android-test/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 3.4.1) - -project(quickjs-android-test) - -add_subdirectory(../quickjs ${CMAKE_CURRENT_BINARY_DIR}/quickjs) diff --git a/android-test/build.gradle b/android-test/build.gradle deleted file mode 100644 index 3ac1439..0000000 --- a/android-test/build.gradle +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.util.zip.CRC32 - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 31 - - defaultConfig { - applicationId 'com.hippo.quickjs.test.android' - minSdkVersion 18 - targetSdkVersion 31 - versionCode 1 - versionName '1.0' - externalNativeBuild { - cmake { - arguments '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' - } - } - } - - sourceSets { - main.assets.srcDirs += 'testassets' - } - - def hasReleaseKey = rootProject.file('release.keystore').exists() - - if (hasReleaseKey) { - signingConfigs { - release { - def properties = new Properties() - properties.load(rootProject.file('local.properties').newDataInputStream()) - storeFile file(properties.getProperty('RELEASE_STORE_PATH')) - storePassword properties.getProperty('RELEASE_STORE_PASSWORD') - keyAlias properties.getProperty('RELEASE_KEY_ALIAS') - keyPassword properties.getProperty('RELEASE_KEY_PASSWORD') - } - } - } - - buildTypes { - release { - debuggable false - jniDebuggable false - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - if (hasReleaseKey) { - signingConfig signingConfigs.release - } - } - } - - externalNativeBuild { - cmake { - path 'CMakeLists.txt' - } - } -} - -task bundleTestAssets(type: Zip) { - doFirst { - delete "${projectDir}/testassets" - file("${projectDir}/testassets").mkdirs() - } - - from "${rootProject.projectDir}/quickjs/quickjs" - exclude '**/*.c', '**/*.h' - archiveName "testassets.zip" - destinationDir file("${projectDir}/testassets") - - doLast { - File testassets = file("${projectDir}/testassets/testassets.zip") - CRC32 crc32 = new CRC32() - testassets.eachByte 4096, { bytes, size -> - crc32.update(bytes, 0, size) - } - new File("${projectDir}/testassets/testassets-${crc32.getValue()}.crc32").createNewFile() - } -} - -project.afterEvaluate { - generateDebugAssets.dependsOn 'bundleTestAssets' - generateReleaseAssets.dependsOn 'bundleTestAssets' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0' - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'net.lingala.zip4j:zip4j:1.3.2' - implementation 'com.getkeepsafe.relinker:relinker:1.3.1' -} diff --git a/android-test/src/main/AndroidManifest.xml b/android-test/src/main/AndroidManifest.xml deleted file mode 100644 index 8a623d3..0000000 --- a/android-test/src/main/AndroidManifest.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/App.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/App.kt deleted file mode 100644 index d6a2e0b..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/App.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -import android.app.Application - -class App : Application() { - - // Let Application holds the Tester instance. - // The tester is lazy. - // It is expected to start when Activity attach the LogView to it. - val tester by lazy { Tester(this).also { it.start() } } -} diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/LogView.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/LogView.kt deleted file mode 100644 index fd3875e..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/LogView.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -import android.content.Context -import android.graphics.Color -import android.graphics.Typeface -import android.graphics.drawable.ColorDrawable -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.ListView -import android.widget.TextView - -/** - * LogView display lots of messages. - */ -class LogView(context: Context) : ListView(context), MessageQueuePrinter { - - private val messages = MessageQueue() - - @Volatile - private var isClosed = false - - private var pendingLastVisiblePosition = 0 - private var lastVisibleBottomShows = true - - val Int.dp: Int - get() { - val f = context.resources.displayMetrics.density * this - return (if (f >= 0) (f + 0.5f) else (f - 0.5f)).toInt() - } - - val Int.sp: Float - get() = context.resources.displayMetrics.scaledDensity * this - - init { - adapter = Adapter(context) - divider = null - selector = ColorDrawable(Color.TRANSPARENT) - clipToPadding = false - setPadding(4.dp, 4.dp, 4.dp, 4.dp) - } - - fun close() { - isClosed = true - } - - private fun postIfNotClosed(block: () -> Unit) { - if (!isClosed) { - post { - if (!isClosed) { - block() - } - } - } - } - - private inline fun catchNewMessages(block: () -> Unit) { - val scrollToBottom = pendingLastVisiblePosition == adapter.count - 1 && lastVisibleBottomShows - block() - (adapter as BaseAdapter).notifyDataSetChanged() - if (scrollToBottom) { - setSelection(adapter.count - 1) - pendingLastVisiblePosition = adapter.count - 1 - lastVisibleBottomShows = true - } - } - - override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) { - super.onScrollChanged(l, t, oldl, oldt) - pendingLastVisiblePosition = lastVisiblePosition - lastVisibleBottomShows = if (childCount > 0) getChildAt(childCount - 1).bottom <= height - paddingBottom else true - } - - override fun print(message: String) { - postIfNotClosed { - catchNewMessages { - messages.add(message) - } - } - } - - override fun print(messages: MessageQueue) { - postIfNotClosed { - catchNewMessages { - this.messages.addAll(messages) - } - } - } - - inner class Adapter(private val context: Context): BaseAdapter() { - - private fun fixMessage(message: String) = - if (message.endsWith("\u001B[K")) message.substring(0, message.length - 3) else message - - override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { - var view = convertView as? TextView - if (view == null) { - view = TextView(context).apply { - typeface = Typeface.MONOSPACE - textSize = 14.0f - setLineSpacing(3.sp, 1.0f) - layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - } - } - view.text = fixMessage(messages[position]) - return view - } - - override fun getItem(position: Int): Any = messages[position] - - override fun getItemId(position: Int): Long = position.toLong() - - override fun getCount(): Int = messages.size - } -} diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/MessagePrinter.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/MessagePrinter.kt deleted file mode 100644 index c03f5ec..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/MessagePrinter.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -interface MessagePrinter { - fun print(message: String) -} - -interface MessageQueuePrinter : MessagePrinter { - fun print(messages: MessageQueue) -} diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/MessageQueue.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/MessageQueue.kt deleted file mode 100644 index 002fc49..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/MessageQueue.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -import java.util.* - -class MessageQueue( - private val bufferSize: Int = 8192 -) { - - constructor(other: MessageQueue): this(other.bufferSize) { - this.messages.addAll(other.messages) - } - - private val messages = LinkedList() - - val size: Int - get() = messages.size - - operator fun get(index: Int): String = messages[index] - - fun add(message: String) { - // Remove the last one if it ends with \u001B[K - if (messages.isNotEmpty()) { - if (messages.last.endsWith("\u001B[K")) { - messages.removeLast() - } - } - - while (messages.size >= bufferSize) { - messages.removeFirst() - } - messages.addLast(message) - } - - fun addAll(messageQueue: MessageQueue) { - messageQueue.messages.forEach { - add(it) - } - } - - fun copy(): MessageQueue = MessageQueue(this) -} diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/TestActivity.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/TestActivity.kt deleted file mode 100644 index 4a5f9db..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/TestActivity.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -import android.app.Activity -import android.os.Bundle -import android.view.Menu -import android.widget.Toast - -class TestActivity : Activity() { - - private lateinit var logView: LogView - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - logView = LogView(this) - setContentView(logView) - (application as App).tester.registerMessageQueuePrinter(logView) - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menu?.add("Send Log File")?.apply { - setOnMenuItemClickListener { - val tester = (application as App).tester - if (tester.isFinished) { - tester.shareLogFile() - } else { - Toast.makeText(this@TestActivity, "The test is not finished", Toast.LENGTH_SHORT).show() - } - true - } - } - return true - } - - override fun onDestroy() { - super.onDestroy() - - logView.close() - } -} diff --git a/android-test/src/main/java/com/hippo/quickjs/android/test/Tester.kt b/android-test/src/main/java/com/hippo/quickjs/android/test/Tester.kt deleted file mode 100644 index fdc103e..0000000 --- a/android-test/src/main/java/com/hippo/quickjs/android/test/Tester.kt +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.quickjs.android.test - -import android.content.Context -import android.content.Intent -import android.net.Uri -import com.getkeepsafe.relinker.ReLinker -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel -import net.lingala.zip4j.core.ZipFile -import java.io.* -import java.lang.ref.WeakReference - -class Tester( - private val context: Context -) { - - private val logFile: File - private val logFileUri: Uri - private val printer: MessageHolder - - private val assetsNameFile = File(context.filesDir, "testassets.name") - private val assetsDir = File(context.filesDir, "testassets") - private val tempFile = File(context.cacheDir, "testassets.zip") - - @Volatile - private var testNumber = 0 - - var isFinished: Boolean = false - private set - - init { - val logDir = File(context.filesDir, "logs") - logDir.mkdirs() - - logFile = File(logDir, "log.txt") - logFileUri = Uri.Builder() - .scheme("content") - .authority("com.hippo.quickjs.android.test.fileprovider") - .appendPath("logs") - .appendPath("log.txt") - .build() - logFile.delete() - - printer = MessageHolder(logFile) - } - - fun registerMessageQueuePrinter(messageQueuePrinter: MessageQueuePrinter) { - printer.registerMessageQueuePrinter(messageQueuePrinter) - } - - private fun ensureAssetFiles() { - val exceptAssetsName = try { - assetsNameFile.readText() - } catch (e: IOException) { - null - } - - var actualAssetsName: String? = null - for (asset in context.assets.list("") ?: emptyArray()) { - if (asset.startsWith("testassets-") && asset.endsWith(".crc32")) { - actualAssetsName = asset - } - } - if (actualAssetsName == null) { - error("Can't find test assets") - } - - if (exceptAssetsName != actualAssetsName) { - printer.print("Need exact assets") - printer.print("except = $exceptAssetsName") - printer.print("actual = $actualAssetsName") - - assetsDir.deleteRecursively() - if (!assetsDir.mkdirs()) { - error("Can't create test assets dir") - } - - context.assets.open("testassets.zip").use { `in` -> - tempFile.outputStream().use { out -> - `in`.copyTo(out) - } - } - - val zipFile = ZipFile(tempFile) - zipFile.extractAll(assetsDir.path) - - assetsNameFile.writeText(actualAssetsName) - - printer.print("All test assets are copied") - } else { - printer.print("All test assets are UP-TO-DATE") - } - } - - private fun ensureExecutable() { - ReLinker.loadLibrary(context, "qjs") - } - - private fun runTest(name: String, executable: String, parameter: String) { - printer.print("********************************") - printer.print("** ${++testNumber}. $name") - printer.print("********************************") - val code = run(executable, parameter) - printer.print("EXIT CODE: $code") - } - - private fun runTest(executable: String, parameter: String) { - val name = "$executable $parameter" - runTest(name, executable, parameter) - } - - private fun js2c() { - runTest("qjsc", "-c -o repl.c -m repl.js") - runTest("qjsc", "-fbignum -c -o qjscalc.c qjscalc.js") - } - - private fun test() { - runTest("qjs", "tests/test_closure.js") - runTest("qjs", "tests/test_language.js") - runTest("qjs", "tests/test_builtin.js") - runTest("qjs", "tests/test_loop.js") - // tmpfile returns null - runTest("qjs", "tests/test_std.js") - runTest("qjs", "tests/test_worker.js") - runTest("qjs", "--bignum tests/test_bjson.js") - runTest("qjs", "examples/test_point.js") - runTest("qjs", "--bignum tests/test_op_overloading.js") - runTest("qjs", "--bignum tests/test_bignum.js") - runTest("qjs", "--qjscalc tests/test_qjscalc.js") - } - - private fun stats() { - runTest("qjs", "-qd") - } - - private fun microbench() { - runTest("qjs", "tests/microbench.js") - } - - private fun runTest262() { - runTest("run-test262", "-m -c test262o.conf") - runTest("run-test262", "-u -c test262o.conf") - runTest("run-test262", "-m -c test262.conf") - runTest("run-test262", "-m -c test262.conf -a") - runTest("run-test262", "-u -c test262.conf -a") - runTest("run-test262", "-m -c test262.conf -E -a") - } - - private fun printThrowable(e: Throwable) { - val baos = ByteArrayOutputStream() - PrintWriter(baos).apply { - e.printStackTrace(this) - flush() - } - ByteArrayInputStream(baos.toByteArray()).reader().buffered().forEachLine { printer.print(it) } - } - - fun start() { - GlobalScope.launch { - try { - ensureAssetFiles() - ensureExecutable() - - js2c() - - test() - stats() - microbench() - runTest262() - - printer.print("********************************") - printer.print("********************************") - printer.print("********************************") - printer.print("TEST COMPLETE") - } catch (e: Throwable) { - e.printStackTrace() - printer.print("********************************") - printer.print("********************************") - printer.print("********************************") - printer.print("TEST INTERRUPT") - printThrowable(e) - } - printer.finish() - - (this + Dispatchers.Main).launch { - isFinished = true - shareLogFile() - } - } - } - - fun shareLogFile() { - val title = "Send Log File" - val intent = Intent(Intent.ACTION_SEND) - intent.type = "text/plain" - intent.putExtra(Intent.EXTRA_STREAM, logFileUri) - intent.putExtra(Intent.EXTRA_SUBJECT, title) - intent.putExtra(Intent.EXTRA_TEXT, title) - val chooser = Intent.createChooser(intent, title) - chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(chooser) - } - - private fun run(executable: String, parameter: String): Int = runBlocking { - val nativeDir = context.applicationInfo.nativeLibraryDir - val executableFile = File(nativeDir, "lib$executable.so") - val command = "${executableFile.path} $parameter" - - val processChannel = Channel() - - val job1 = (GlobalScope + Dispatchers.IO).launch { - val process = processChannel.receive() - process.inputStream.reader().buffered().forEachLine { printer.print(it) } - } - - val job2 = (GlobalScope + Dispatchers.IO).launch { - val process = processChannel.receive() - process.errorStream.reader().buffered().forEachLine { printer.print(it) } - } - - val process = Runtime.getRuntime().exec(command, null, assetsDir) - processChannel.send(process) - processChannel.send(process) - val code = process.waitFor() - - job1.join() - job2.join() - - code - } - - /** - * MessageList cache messages and dispatch message to the last registered MultiPrinter. - */ - private class MessageHolder( - logFile: File - ) : MessagePrinter { - - private val messages = MessageQueue() - private val writer = logFile.writer() - - @Volatile - private var weakMessageQueuePrinter: WeakReference? = null - - @Synchronized - fun registerMessageQueuePrinter(messageQueuePrinter: MessageQueuePrinter) { - messageQueuePrinter.print(messages.copy()) - weakMessageQueuePrinter = WeakReference(messageQueuePrinter) - } - - @Synchronized - override fun print(message: String) { - messages.add(message) - weakMessageQueuePrinter?.get()?.print(message) - if (!message.endsWith("\u001B[K")) { - writer.write(message) - writer.write("\n") - } - } - - fun finish() { - writer.flush() - writer.close() - } - } -} diff --git a/android-test/src/main/res/xml/file_paths.xml b/android-test/src/main/res/xml/file_paths.xml deleted file mode 100644 index 7c44583..0000000 --- a/android-test/src/main/res/xml/file_paths.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/build.gradle b/build.gradle index 3ec10eb..211f17a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,44 +1,4 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -buildscript { - repositories { - google() - mavenCentral() - //noinspection JcenterRepositoryObsolete - jcenter() - maven { url 'https://plugins.gradle.org/m2/' } - } - dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - } -} - -allprojects { - repositories { - google() - mavenCentral() - //noinspection JcenterRepositoryObsolete - jcenter() - maven { url 'https://jitpack.io' } - } -} - -task clean(type: Delete) { - delete rootProject.buildDir +plugins { + id "org.jetbrains.kotlin.android" version "1.9.24" apply false + id 'com.android.library' version '8.5.2' apply false } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 415663e..b5ed8a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Oct 17 02:15:12 CST 2020 +#Wed Sep 17 17:40:00 AMT 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip diff --git a/library/build.gradle b/library/build.gradle index 31d4bd8..ccaaf42 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,43 +1,27 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'com.android.library' +plugins { + id 'com.android.library' +} android { - compileSdkVersion 31 + compileSdkVersion 34 + + ndkVersion "27.3.13750724" defaultConfig { - minSdkVersion 18 - targetSdkVersion 31 + minSdkVersion 23 + targetSdkVersion 35 testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' externalNativeBuild { cmake { targets 'quickjs-android' - arguments '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' + arguments '-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON' } } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - sourceSets { - androidTest.java.srcDirs += 'src/androidTest/kotlin' + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } buildTypes { @@ -61,3 +45,7 @@ dependencies { androidTestImplementation 'junit:junit:4.13.2' androidTestImplementation 'org.assertj:assertj-core:3.13.2' } + +android { + namespace 'com.hippo.quickjs.android' +} diff --git a/settings.gradle b/settings.gradle index 651f5df..e07bed1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,18 +1,20 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -include ':android-test' +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url "https://plugins.gradle.org/m2/" } + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { url "https://plugins.gradle.org/m2/" } + maven { url "https://jitpack.io" } + maven { url "https://zendesk.jfrog.io/artifactory/repo" } + } +} include ':library' From 9b0c99361a8704699d3db9b939a82c5a0d5f7b1b Mon Sep 17 00:00:00 2001 From: Andrey Rylov Date: Wed, 17 Sep 2025 18:59:53 +0400 Subject: [PATCH 3/3] add publishing --- android-maven-gradle.gradle | 49 ------------------------------------- library/build.gradle | 6 +++++ 2 files changed, 6 insertions(+), 49 deletions(-) delete mode 100644 android-maven-gradle.gradle diff --git a/android-maven-gradle.gradle b/android-maven-gradle.gradle deleted file mode 100644 index 72b8b37..0000000 --- a/android-maven-gradle.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'com.github.dcendents.android-maven' - -tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' -} - -tasks.withType(Javadoc) { - options.encoding = 'UTF-8' - failOnError false -} - -// build a jar with source files -task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' -} - -task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.sourceFiles - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - classpath += configurations.compile -} - -// build a jar with javadoc -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -artifacts { - archives sourcesJar - archives javadocJar -} diff --git a/library/build.gradle b/library/build.gradle index ccaaf42..2771d83 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -36,6 +36,12 @@ android { path 'CMakeLists.txt' } } + + publishing { + singleVariant('release') { + withSourcesJar() + } + } } dependencies {