6.7.0 - Alpha14 - 新增 http.put/del(ete)/head 方法; 新增 http.xxxAsync 方法, 用于异步网络请求 (issue #423)
This commit is contained in:
@@ -32,9 +32,11 @@ import org.autojs.autojs.util.RhinoUtils.coerceIntNumber
|
||||
import org.autojs.autojs.util.RhinoUtils.coerceLongNumber
|
||||
import org.autojs.autojs.util.RhinoUtils.coerceObject
|
||||
import org.autojs.autojs.util.RhinoUtils.coerceString
|
||||
import org.autojs.autojs.util.RhinoUtils.handleAsyncOperation
|
||||
import org.autojs.autojs.util.RhinoUtils.isUiThread
|
||||
import org.autojs.autojs.util.RhinoUtils.js_json_stringify
|
||||
import org.autojs.autojs.util.RhinoUtils.newNativeObject
|
||||
import org.autojs.autojs.util.RhinoUtils.withRhinoContext
|
||||
import org.mozilla.javascript.BaseFunction
|
||||
import org.mozilla.javascript.Context
|
||||
import org.mozilla.javascript.NativeObject
|
||||
@@ -53,10 +55,23 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
override val selfAssignmentFunctions = listOf(
|
||||
::buildRequest.name,
|
||||
::request.name,
|
||||
::requestAsync.name,
|
||||
::get.name,
|
||||
::getAsync.name,
|
||||
::head.name,
|
||||
::headAsync.name,
|
||||
::post.name,
|
||||
::postAsync.name,
|
||||
::postJson.name,
|
||||
::postJsonAsync.name,
|
||||
::postMultipart.name,
|
||||
::postMultipartAsync.name,
|
||||
"put",
|
||||
::putAsync.name,
|
||||
::delete.name,
|
||||
::del.name,
|
||||
::deleteAsync.name,
|
||||
::delAsync.name,
|
||||
)
|
||||
|
||||
companion object : Augmentable() {
|
||||
@@ -74,7 +89,10 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
private const val KEY_BODY_CACHE_THRESHOLD_BYTES = "bodyCacheThresholdBytes"
|
||||
|
||||
private const val METHOD_GET = "GET"
|
||||
private const val METHOD_HEAD = "HEAD"
|
||||
private const val METHOD_POST = "POST"
|
||||
private const val METHOD_PUT = "PUT"
|
||||
private const val METHOD_DELETE = "DELETE"
|
||||
|
||||
private val DEFAULT_CONTENT_TYPE = Mime.APPLICATION_X_WWW_FORM_URLENCODED
|
||||
|
||||
@@ -117,31 +135,22 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun requestRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, options: Any? = null, callback: Any? = null): Any {
|
||||
|
||||
val cont: Creator? = when {
|
||||
callback.isJsFunction() && isUiThread() && Continuation.isEnabled(scriptRuntime) -> Continuation.createRhinoWithRuntime(scriptRuntime)
|
||||
else -> null
|
||||
}
|
||||
|
||||
val opt = coerceObject(options, newNativeObject())
|
||||
|
||||
scriptRuntime.http.okhttp.apply {
|
||||
maxRetries = coerceIntNumber(opt.prop(KEY_MAX_RETRIES), DEFAULT_MAX_RETRIES)
|
||||
applyOkHttpClientBuilder(opt)
|
||||
}
|
||||
|
||||
val cacheBody = opt.inquire(KEY_CACHE_BODY, ::coerceBoolean, DEFAULT_CACHE_BODY)
|
||||
val cacheThreshold = coerceLongNumber(opt.prop(KEY_BODY_CACHE_THRESHOLD_BYTES), DEFAULT_BODY_CACHE_THRESHOLD_BYTES)
|
||||
|
||||
val newCall = scriptRuntime.http.client().newCall(buildRequestRhinoWithRuntime(scriptRuntime, url, options))
|
||||
val prepared = prepareRequest(scriptRuntime, url, options)
|
||||
|
||||
if (!callback.isJsFunction() && cont == null) {
|
||||
return ResponseWrapper(scriptRuntime, newCall.execute(), cacheBody, cacheThreshold).wrap()
|
||||
return wrapResponse(scriptRuntime, prepared.call.execute(), prepared.cacheBody, prepared.cacheThreshold)
|
||||
}
|
||||
|
||||
scriptRuntime.loopers.waitWhenIdle(true)
|
||||
newCall.enqueue(object : Callback {
|
||||
prepared.call.enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val wrappedResponse = ResponseWrapper(scriptRuntime, response, cacheBody, cacheThreshold).wrap()
|
||||
val wrappedResponse = wrapResponse(scriptRuntime, response, prepared.cacheBody, prepared.cacheThreshold)
|
||||
cont?.resume(wrappedResponse)
|
||||
if (callback is BaseFunction) {
|
||||
scriptRuntime.bridges.call(callback, callback, arrayOf(wrappedResponse, null))
|
||||
@@ -157,10 +166,49 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
scriptRuntime.loopers.waitWhenIdle(false)
|
||||
}
|
||||
})
|
||||
|
||||
cont?.await()
|
||||
return UNDEFINED
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun requestAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..3) {
|
||||
val (url, options, callback) = it
|
||||
requestAsyncRhinoWithRuntime(scriptRuntime, url, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun requestAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
|
||||
val prepared = prepareRequest(scriptRuntime, url, options)
|
||||
|
||||
return handleAsyncOperation(
|
||||
scriptRuntime,
|
||||
operation = {
|
||||
// Execute network call in background thread.
|
||||
// zh-CN: 在后台线程执行网络请求.
|
||||
prepared.call.execute()
|
||||
},
|
||||
uiMapper = { response ->
|
||||
// Wrap response into Rhino object on UI thread with Rhino Context.
|
||||
// zh-CN: 在 UI 线程进入 Rhino Context, 将 Response 包装为 Rhino 对象.
|
||||
withRhinoContext {
|
||||
val wrapped = wrapResponse(scriptRuntime, response, prepared.cacheBody, prepared.cacheThreshold)
|
||||
|
||||
// Optional: if user provided callback, call it on UI thread.
|
||||
// zh-CN: 可选: 如果用户提供了 callback, 则在 UI 线程调用.
|
||||
if (callback is BaseFunction) {
|
||||
scriptRuntime.bridges.call(callback, callback, arrayOf(wrapped, null))
|
||||
}
|
||||
wrapped
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun get(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..3) {
|
||||
@@ -168,6 +216,57 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
getRhinoWithRuntime(scriptRuntime, url, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun head(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..3) {
|
||||
val (url, options, callback) = it
|
||||
headRhinoWithRuntime(scriptRuntime, url, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun headAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..3) {
|
||||
val (url, options, callback) = it
|
||||
headAsyncRhinoWithRuntime(scriptRuntime, url, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun headRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, options: Any? = null, callback: Any? = null): Any {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.head must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_HEAD)
|
||||
return requestRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun headAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.headAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_HEAD)
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun getAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..3) {
|
||||
val (url, options, callback) = it
|
||||
getAsyncRhinoWithRuntime(scriptRuntime, url, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun getAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.getAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_GET)
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
@@ -178,6 +277,96 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
return requestRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun put(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
putRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun putAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
putAsyncRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun putRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any? = null, options: Any? = null, callback: Any? = null): Any {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.put must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_PUT)
|
||||
putIfAbsent(niceOptions, KEY_CONTENT_TYPE to DEFAULT_CONTENT_TYPE)
|
||||
fillPostData(niceOptions, data)
|
||||
return requestRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun putAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any? = null, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.putAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_PUT)
|
||||
putIfAbsent(niceOptions, KEY_CONTENT_TYPE to DEFAULT_CONTENT_TYPE)
|
||||
fillPostData(niceOptions, data)
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun delete(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
deleteRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun del(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
deleteRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun deleteAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
deleteAsyncRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun delAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
deleteAsyncRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun deleteRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any? = null, options: Any? = null, callback: Any? = null): Any {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.delete must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_DELETE)
|
||||
putIfAbsent(niceOptions, KEY_CONTENT_TYPE to DEFAULT_CONTENT_TYPE)
|
||||
fillPostData(niceOptions, data)
|
||||
return requestRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun deleteAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any? = null, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.deleteAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_DELETE)
|
||||
putIfAbsent(niceOptions, KEY_CONTENT_TYPE to DEFAULT_CONTENT_TYPE)
|
||||
fillPostData(niceOptions, data)
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun post(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Any = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
@@ -185,6 +374,25 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
postRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun postAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
postAsyncRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun postAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any? = null, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.postAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_METHOD to METHOD_POST)
|
||||
putIfAbsent(niceOptions, KEY_CONTENT_TYPE to DEFAULT_CONTENT_TYPE)
|
||||
fillPostData(niceOptions, data)
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
@@ -204,6 +412,23 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
postJsonRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun postJsonAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, data, options, callback) = it
|
||||
postJsonAsyncRhinoWithRuntime(scriptRuntime, url, data, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun postJsonAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, data: Any?, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.postJsonAsync must be a JavaScript Object" }
|
||||
put(niceOptions, KEY_CONTENT_TYPE to Mime.APPLICATION_JSON)
|
||||
return postAsyncRhinoWithRuntime(scriptRuntime, url, data, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
@@ -221,6 +446,27 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
postMultipartRhinoWithRuntime(scriptRuntime, url, files, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun postMultipartAsync(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeObject = ensureArgumentsLengthInRange(args, 1..4) {
|
||||
val (url, files, options, callback) = it
|
||||
postMultipartAsyncRhinoWithRuntime(scriptRuntime, url, files, options, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
fun postMultipartAsyncRhinoWithRuntime(scriptRuntime: ScriptRuntime, url: Any?, files: Any?, options: Any? = null, callback: Any? = null): NativeObject {
|
||||
val niceOptions = if (options.isJsNullish()) newNativeObject() else options
|
||||
require(niceOptions is NativeObject) { "Argument \"options\" ${options.jsBrief()} for http.postMultipartAsync must be a JavaScript Object" }
|
||||
listOf(
|
||||
KEY_METHOD to METHOD_POST,
|
||||
KEY_CONTENT_TYPE to Mime.MULTIPART_FORM_DATA,
|
||||
KEY_FILES to files,
|
||||
).let { list -> put(niceOptions, list) }
|
||||
return requestAsyncRhinoWithRuntime(scriptRuntime, url, niceOptions, callback)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
@RhinoFunctionBody
|
||||
@@ -253,6 +499,49 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
|
||||
}
|
||||
}
|
||||
|
||||
private data class PreparedRequest(
|
||||
val call: Call,
|
||||
val cacheBody: Boolean,
|
||||
val cacheThreshold: Long,
|
||||
)
|
||||
|
||||
private fun prepareRequest(scriptRuntime: ScriptRuntime, url: Any?, options: Any?): PreparedRequest {
|
||||
|
||||
// Normalize options as a NativeObject.
|
||||
// zh-CN: 将 options 规范化为 NativeObject.
|
||||
val opt = coerceObject(options, newNativeObject())
|
||||
|
||||
// Apply OkHttp runtime configs (retries/client builder).
|
||||
// zh-CN: 应用 OkHttp 运行时配置 (重试/Client Builder).
|
||||
scriptRuntime.http.okhttp.apply {
|
||||
maxRetries = coerceIntNumber(opt.prop(KEY_MAX_RETRIES), DEFAULT_MAX_RETRIES)
|
||||
applyOkHttpClientBuilder(opt)
|
||||
}
|
||||
|
||||
// Cache policy for response body wrapper.
|
||||
// zh-CN: Response body wrapper 的缓存策略.
|
||||
val cacheBody = opt.inquire(KEY_CACHE_BODY, ::coerceBoolean, DEFAULT_CACHE_BODY)
|
||||
val cacheThreshold = coerceLongNumber(opt.prop(KEY_BODY_CACHE_THRESHOLD_BYTES), DEFAULT_BODY_CACHE_THRESHOLD_BYTES)
|
||||
|
||||
// Build request with normalized options and create call.
|
||||
// zh-CN: 使用规范化后的 options 构建 Request 并创建 Call.
|
||||
val request = buildRequestRhinoWithRuntime(scriptRuntime, url, opt)
|
||||
val call = scriptRuntime.http.client().newCall(request)
|
||||
|
||||
return PreparedRequest(
|
||||
call = call,
|
||||
cacheBody = cacheBody,
|
||||
cacheThreshold = cacheThreshold,
|
||||
)
|
||||
}
|
||||
|
||||
private fun wrapResponse(scriptRuntime: ScriptRuntime, response: Response, cacheBody: Boolean, cacheThreshold: Long): Any {
|
||||
|
||||
// Wrap okhttp3.Response into a Rhino-friendly object.
|
||||
// zh-CN: 将 okhttp3.Response 包装为 Rhino 可用对象.
|
||||
return ResponseWrapper(scriptRuntime, response, cacheBody, cacheThreshold).wrap()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -913,6 +913,14 @@ object RhinoUtils {
|
||||
}
|
||||
|
||||
fun handleAsyncOperation(scriptRuntime: ScriptRuntime, func: () -> Any?): NativeObject {
|
||||
return handleAsyncOperation(scriptRuntime, func) { it }
|
||||
}
|
||||
|
||||
fun <T> handleAsyncOperation(
|
||||
scriptRuntime: ScriptRuntime,
|
||||
operation: () -> T,
|
||||
uiMapper: (T) -> Any?,
|
||||
): NativeObject {
|
||||
val promiseAdapter = ScriptPromiseAdapter()
|
||||
|
||||
// Use Android Thread directly to avoid coupling with JS threads/loopers here.
|
||||
@@ -921,12 +929,19 @@ object RhinoUtils {
|
||||
try {
|
||||
// Do the blocking work (e.g. network request) in background thread.
|
||||
// zh-CN: 在后台线程执行阻塞式操作 (如网络请求).
|
||||
val result = func.invoke()
|
||||
val result = operation.invoke()
|
||||
|
||||
// Resolve on UI thread so that UI scripts can safely touch `ui.*` in then().
|
||||
// zh-CN: 在 UI 线程 resolve, 让 UI 脚本在 then() 中可安全操作 `ui.*`.
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
promiseAdapter.resolve(result)
|
||||
try {
|
||||
// Map result on UI thread (e.g. wrap Java objects into Rhino objects).
|
||||
// zh-CN: 在 UI 线程映射结果 (例如将 Java 对象包装为 Rhino 对象).
|
||||
val mapped = uiMapper.invoke(result)
|
||||
promiseAdapter.resolve(mapped)
|
||||
} catch (t: Throwable) {
|
||||
promiseAdapter.reject(t)
|
||||
}
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
// Reject on UI thread for consistent callback threading.
|
||||
@@ -942,7 +957,6 @@ object RhinoUtils {
|
||||
return callFunction(scriptRuntime, scriptRuntime.js_ResultAdapter, "promise", arrayOf(promiseAdapter)) as NativeObject
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun Class<*>.getRhinoStandardFunctionMethods(): List<Method> {
|
||||
return this.declaredMethods.filter {
|
||||
|
||||
Reference in New Issue
Block a user