From 35fe093e5c6b187069c631e4edbb58f1d9440b0c Mon Sep 17 00:00:00 2001 From: Kelvin Date: Mon, 6 Oct 2025 19:13:52 +0200 Subject: [PATCH] Convert promise cancel exceptions to conventional exceptions --- .../com/futo/platformplayer/Extensions_V8.kt | 16 +++++++++ .../platformplayer/casting/StateCasting.kt | 3 +- .../futo/platformplayer/engine/V8Plugin.kt | 35 +++++++++++++------ .../engine/packages/PackageHttp.kt | 2 +- .../views/video/FutoVideoPlayerBase.kt | 5 +-- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/Extensions_V8.kt b/app/src/main/java/com/futo/platformplayer/Extensions_V8.kt index bee729a4..3166613e 100644 --- a/app/src/main/java/com/futo/platformplayer/Extensions_V8.kt +++ b/app/src/main/java/com/futo/platformplayer/Extensions_V8.kt @@ -7,6 +7,7 @@ import com.caoccao.javet.values.reference.V8ValueArray import com.caoccao.javet.values.reference.V8ValueError import com.caoccao.javet.values.reference.V8ValueObject import com.caoccao.javet.values.reference.V8ValuePromise +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.exceptions.ScriptExecutionException @@ -300,10 +301,13 @@ fun V8ValuePromise.toV8ValueAsync(plugin: V8Plugin): V8Deferred fun V8Value.toException(config: IV8PluginConfig): Throwable { val p0 = this; if(p0 is V8ValueObject) { + return V8Plugin.getExceptionFromPlugin(config, p0, null, null, null, "P:"); + /* val pluginType = p0.getOrDefault(config, "plugin_type", "Promise Exception", "")?.let { if(!it.isNullOrBlank()) it + "" else "" } val msg = p0.getOrDefault(config, "msg", "Promise Exception", null) ?: p0.getOrDefault(config, "message", "Promise Exception", ""); return Throwable("Promise Failed: " + pluginType + msg); + */ } else if(p0 is V8ValueString) return Throwable("Promise Failed:" + p0.value); @@ -371,4 +375,16 @@ fun V8ValueObject.invokeV8VoidAsync(method: String, vararg obj: Any?): V8Deferre return result; } return V8Deferred(CompletableDeferred(result)); +} + +suspend fun Deferred.awaitCancelConverted(): T { + try { + return this.await(); + } + catch(ex: CancellationException) { + if(ex.cause != null) { + throw ex.cause!!; + } + throw ex; + } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt index 4c3e3323..e5f8e68e 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt @@ -33,6 +33,7 @@ import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManif import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawAudioSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSSource +import com.futo.platformplayer.awaitCancelConverted import com.futo.platformplayer.builders.DashBuilder import com.futo.platformplayer.models.CastingDeviceInfo import com.futo.platformplayer.constructs.Event1 @@ -1183,7 +1184,7 @@ abstract class StateCasting { onLoading?.invoke(true) } } - deferred.await() + deferred.awaitCancelConverted() } finally { if (castId == _castId.get()) { withContext(Dispatchers.Main) { diff --git a/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt b/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt index 9b350458..3ebc7259 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt @@ -18,6 +18,7 @@ import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.engine.exceptions.NoInternetException import com.futo.platformplayer.engine.exceptions.PluginEngineStoppedException +import com.futo.platformplayer.engine.exceptions.PluginException import com.futo.platformplayer.engine.exceptions.ScriptAgeException import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException import com.futo.platformplayer.engine.exceptions.ScriptCompilationException @@ -36,6 +37,7 @@ import com.futo.platformplayer.engine.packages.PackageHttp import com.futo.platformplayer.engine.packages.PackageJSDOM import com.futo.platformplayer.engine.packages.PackageUtilities import com.futo.platformplayer.engine.packages.V8Package +import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrThrow import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateAssets @@ -513,18 +515,29 @@ class V8Plugin { } private fun throwExceptionFromV8(config: IV8PluginConfig, pluginType: String, msg: String, innerEx: Exception? = null, stack: String? = null, code: String? = null) { + throw getExceptionFromPlugin(config, pluginType, msg, innerEx, stack, code); + } + fun getExceptionFromPlugin(config: IV8PluginConfig, obj: V8ValueObject, innerEx: Exception? = null, stack: String? = null, code: String? = null, prefix: String? = null): PluginException { + val pluginType = obj.getOrDefault(config, "plugin_type", "Exception Handling", "")?.let { if(!it.isNullOrBlank()) it + "" else "" } ?: ""; + var msg = obj.getOrDefault(config, "msg", "Exception Handling", null) + ?: obj.getOrDefault(config, "message", "Exception Handling", ""); + if(!prefix.isNullOrBlank()) + msg = prefix + msg; + return getExceptionFromPlugin(config, pluginType, msg ?: "Unknown exception", innerEx, stack, code); + } + fun getExceptionFromPlugin(config: IV8PluginConfig, pluginType: String, msg: String, innerEx: Exception? = null, stack: String? = null, code: String? = null): PluginException { when(pluginType) { - "ScriptException" -> throw ScriptException(config, msg, innerEx, stack, code); - "CriticalException" -> throw ScriptCriticalException(config, msg, innerEx, stack, code); - "AgeException" -> throw ScriptAgeException(config, msg, innerEx, stack, code); - "UnavailableException" -> throw ScriptUnavailableException(config, msg, innerEx, stack, code); - "ScriptLoginRequiredException" -> throw ScriptLoginRequiredException(config, msg, innerEx, stack, code); - "ScriptExecutionException" -> throw ScriptExecutionException(config, msg, innerEx, stack, code); - "ScriptCompilationException" -> throw ScriptCompilationException(config, msg, innerEx, code); - "ScriptImplementationException" -> throw ScriptImplementationException(config, msg, innerEx, null, code); - "ScriptTimeoutException" -> throw ScriptTimeoutException(config, msg, innerEx); - "NoInternetException" -> throw NoInternetException(config, msg, innerEx, stack, code); - else -> throw ScriptExecutionException(config, msg, innerEx, stack, code); + "ScriptException" -> return ScriptException(config, msg, innerEx, stack, code); + "CriticalException" -> return ScriptCriticalException(config, msg, innerEx, stack, code); + "AgeException" -> return ScriptAgeException(config, msg, innerEx, stack, code); + "UnavailableException" -> return ScriptUnavailableException(config, msg, innerEx, stack, code); + "ScriptLoginRequiredException" -> return ScriptLoginRequiredException(config, msg, innerEx, stack, code); + "ScriptExecutionException" -> return ScriptExecutionException(config, msg, innerEx, stack, code); + "ScriptCompilationException" -> return ScriptCompilationException(config, msg, innerEx, code); + "ScriptImplementationException" -> return ScriptImplementationException(config, msg, innerEx, null, code); + "ScriptTimeoutException" -> return ScriptTimeoutException(config, msg, innerEx); + "NoInternetException" -> return NoInternetException(config, msg, innerEx, stack, code); + else -> return ScriptExecutionException(config, msg, innerEx, stack, code); } } diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt index d7aa89b7..a6068a8c 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt @@ -254,7 +254,7 @@ class PackageHttp: V8Package { //TODO: This object is currently re-wrapped each modification, this is due to an issue passing the same object back and forth, should be fixed in future. @V8Convert(mode = V8ConversionMode.AllowOnly, proxyMode = V8ProxyMode.Class) - class BatchBuilder(private val _package: PackageHttp, existingRequests: MutableList> = mutableListOf()): V8BindObject() { + class BatchBuilder(@Transient private val _package: PackageHttp, existingRequests: MutableList> = mutableListOf()): V8BindObject() { @Transient private val _reqs = existingRequests; diff --git a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt index 37cbe052..2c2cf4ee 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt @@ -69,6 +69,7 @@ import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalAud import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalVideoContentSource import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalVideoFileSource import com.futo.platformplayer.api.media.structures.IPager +import com.futo.platformplayer.awaitCancelConverted import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.TaskHandler @@ -643,7 +644,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout { setLoading(true) } } - val generated = generatedDef.await(); + val generated = generatedDef.awaitCancelConverted(); if (_swapIdVideo.get() != swapId) { return@launch } @@ -807,7 +808,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout { setLoading(true) } } - val generated = generatedDef.await(); + val generated = generatedDef.awaitCancelConverted(); if (_swapIdAudio.get() != swapId) { return@launch }