6.7.0 - Alpha19 - 修复内置模块方法调用可能出现 Rhino 上下文可能不一致的问题

This commit is contained in:
SuperMonster003
2026-01-31 15:09:08 +08:00
parent 8205409c8c
commit 142c465914
19 changed files with 231 additions and 245 deletions

View File

@@ -1,7 +1,7 @@
{ {
"$data": { "$data": {
"v6.7.0": { "v6.7.0": {
"released_date": "2026/01/30", "released_date": "2026/01/31",
"feature": [ "feature": [
"插件中心功能, 支持插件的安装/卸载/更新等操作 (入口: 主页抽屉按钮/主页标签页)", "插件中心功能, 支持插件的安装/卸载/更新等操作 (入口: 主页抽屉按钮/主页标签页)",
"Paddle OCR (PP-OCRv5) 插件, 用于光学字符识别", "Paddle OCR (PP-OCRv5) 插件, 用于光学字符识别",
@@ -79,6 +79,7 @@
"ocr.detect 方法获得的结果可能与 ocr.mode 不匹配的问题 _[`issue #468`](http://issues.autojs6.com/468)_", "ocr.detect 方法获得的结果可能与 ocr.mode 不匹配的问题 _[`issue #468`](http://issues.autojs6.com/468)_",
"auto.registerEvent 注册的无障碍服务事件会被其他脚本误清理的问题 _[`issue #466`](http://issues.autojs6.com/466)_ _[`issue #343`](http://issues.autojs6.com/343#issuecomment-3263953918)_", "auto.registerEvent 注册的无障碍服务事件会被其他脚本误清理的问题 _[`issue #466`](http://issues.autojs6.com/466)_ _[`issue #343`](http://issues.autojs6.com/343#issuecomment-3263953918)_",
"Android 10 UiObject#child 方法可能出现 ArrayIndexOutOfBoundsException 异常的问题 _[`issue #416`](http://issues.autojs6.com/416)_", "Android 10 UiObject#child 方法可能出现 ArrayIndexOutOfBoundsException 异常的问题 _[`issue #416`](http://issues.autojs6.com/416)_",
"内置模块方法调用可能出现 Rhino 上下文可能不一致的问题",
"脚本创建大量浮动窗口后, 脚本退出时可能出现窗口残留的问题", "脚本创建大量浮动窗口后, 脚本退出时可能出现窗口残留的问题",
"运行项目时 project.json 配置参数可能无法正常解析的问题", "运行项目时 project.json 配置参数可能无法正常解析的问题",
"项目打包时 project.json 的 excludedDirs 配置参数将导致配置文件解析失败的问题 _[`issue #428`](http://issues.autojs6.com/428)_", "项目打包时 project.json 的 excludedDirs 配置参数将导致配置文件解析失败的问题 _[`issue #428`](http://issues.autojs6.com/428)_",

View File

@@ -1,6 +1,7 @@
package org.autojs.autojs.rhino.extension package org.autojs.autojs.rhino.extension
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.util.RhinoUtils.getOrCreateStandardObjects
import org.autojs.autojs.util.RhinoUtils.withRhinoContext import org.autojs.autojs.util.RhinoUtils.withRhinoContext
import org.mozilla.javascript.Context import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeArray import org.mozilla.javascript.NativeArray
@@ -9,7 +10,7 @@ object ArrayExtensions {
fun Array<*>.toNativeArray(): NativeArray { fun Array<*>.toNativeArray(): NativeArray {
return withRhinoContext { cx -> return withRhinoContext { cx ->
val standardObjects = cx.initStandardObjects() val standardObjects = cx.getOrCreateStandardObjects()
cx.newArray(standardObjects, this.toList().map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray cx.newArray(standardObjects, this.toList().map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
} }
} }

View File

@@ -1,6 +1,7 @@
package org.autojs.autojs.rhino.extension package org.autojs.autojs.rhino.extension
import org.autojs.autojs.util.RhinoUtils import org.autojs.autojs.util.RhinoUtils
import org.autojs.autojs.util.RhinoUtils.getOrCreateStandardObjects
import org.mozilla.javascript.Context import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeArray import org.mozilla.javascript.NativeArray
@@ -8,7 +9,7 @@ object IterableExtensions {
fun Iterable<*>.toNativeArray(): NativeArray { fun Iterable<*>.toNativeArray(): NativeArray {
return RhinoUtils.withRhinoContext { cx -> return RhinoUtils.withRhinoContext { cx ->
val standardObjects = cx.initStandardObjects() val standardObjects = cx.getOrCreateStandardObjects()
cx.newArray(standardObjects, this.map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray cx.newArray(standardObjects, this.map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
} }
} }

View File

@@ -13,5 +13,5 @@ interface IScriptBridges {
fun toString(obj: Any?): String fun toString(obj: Any?): String
fun toPrimitive(obj: Any?): Any fun toPrimitive(obj: Any?): Any?
} }

View File

@@ -29,12 +29,12 @@ class ScriptBridges : IScriptBridges {
this.engine = engine this.engine = engine
} }
fun setJavaPrimitiveWrap(b: Boolean) = useJsContext { fun setJavaPrimitiveWrap(b: Boolean) = useJsContext { cx ->
it.wrapFactory.isJavaPrimitiveWrap = b cx.wrapFactory.isJavaPrimitiveWrap = b
} }
fun isJavaPrimitiveWrap(): Boolean = useJsContext { fun isJavaPrimitiveWrap(): Boolean = useJsContext { cx ->
it.wrapFactory.isJavaPrimitiveWrap cx.wrapFactory.isJavaPrimitiveWrap
} }
override fun call(func: BaseFunction, target: Any?, args: Array<*>) = useJsContext { cx -> override fun call(func: BaseFunction, target: Any?, args: Array<*>) = useJsContext { cx ->
@@ -46,12 +46,12 @@ class ScriptBridges : IScriptBridges {
callFunction(engine.runtime, func, niceScope, thisObj, niceArgs) callFunction(engine.runtime, func, niceScope, thisObj, niceArgs)
} }
override fun toArray(o: Iterable<*>?): NativeArray = useJsContext { context -> override fun toArray(o: Iterable<*>?): NativeArray = useJsContext { cx ->
val scope = context.initStandardObjects() val scope = engine.runtime.topLevelScope
context.newArray(scope, o?.map { Context.javaToJS(it, scope) }?.toTypedArray()) as NativeArray cx.newArray(scope, o?.map { Context.javaToJS(it, scope) }?.toTypedArray()) as NativeArray
} }
override fun asArray(listLike: Any): NativeArray = useJsContext { context -> override fun asArray(listLike: Any): NativeArray = useJsContext { cx ->
if (listLike is Iterable<*>) { if (listLike is Iterable<*>) {
return@useJsContext toArray(listLike) return@useJsContext toArray(listLike)
} }
@@ -61,7 +61,7 @@ class ScriptBridges : IScriptBridges {
listLike::class.java.methods.forEach { listLike::class.java.methods.forEach {
val name = it.name val name = it.name
val method = NativeJavaMethod(it, name) val method = NativeJavaMethod(it, name)
val bound = BoundFunction(context, arr, method, boundThis, emptyArray()) val bound = BoundFunction(cx, arr, method, boundThis, emptyArray())
arr.put(name, arr, bound) arr.put(name, arr, bound)
} }
return@useJsContext arr return@useJsContext arr
@@ -69,16 +69,18 @@ class ScriptBridges : IScriptBridges {
return@useJsContext newNativeArray() return@useJsContext newNativeArray()
} }
override fun toString(obj: Any?): String = Context.toString(obj) override fun toString(obj: Any?): String =
Context.toString(obj)
override fun toPrimitive(obj: Any?): Any = useJsContext { context -> override fun toPrimitive(obj: Any?): Any? =
Context.javaToJS(obj, context.initStandardObjects()) Context.javaToJS(obj, engine.runtime.topLevelScope)
}
private fun <T> useJsContext(f: (Context) -> T): T { private fun <T> useJsContext(f: (Context) -> T): T {
val currentContext = Context.getCurrentContext() val currentContext = Context.getCurrentContext()
return try { return try {
f(currentContext ?: engine.setupContext(Context.enter())) // Enter Context via engine to ensure WrapFactory and AutoJsContext binding are installed.
// zh-CN: 通过 engine 进入 Context, 确保 WrapFactory 与 AutoJsContext 绑定已安装.
f(currentContext ?: engine.enterContext())
} finally { } finally {
currentContext ?: Context.exit() currentContext ?: Context.exit()
} }

View File

@@ -82,7 +82,7 @@ open class AugmentableProxy(private val scriptRuntime: ScriptRuntime) : Augmenta
// ! but defined in a certain object in its prototype chain. // ! but defined in a certain object in its prototype chain.
// ! zh-CN: 表示 `key` 未定义在 `augmented` 上, 但定义在其原型链对象上. // ! zh-CN: 表示 `key` 未定义在 `augmented` 上, 但定义在其原型链对象上.
!augmented.has(key) && ScriptableObject.hasProperty(augmented, key) -> { !augmented.has(key) && ScriptableObject.hasProperty(augmented, key) -> {
withRhinoContext { cx -> BoundFunction(cx, augmented, value, augmented, arrayOf()) } withRhinoContext(scriptRuntime) { cx -> BoundFunction(cx, augmented, value, augmented, arrayOf()) }
} }
else -> value else -> value
} }

View File

@@ -309,7 +309,12 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
val last = it.last() val last = it.last()
when { when {
isGestureResultCallbackLike(last) -> { isGestureResultCallbackLike(last) -> {
scriptRuntime.automator.gestureAsync(start, duration, toPointsGroup(it.drop(1).dropLast(1)).toTypedArray<IntArray>(), toGestureResultCallback(last)) scriptRuntime.automator.gestureAsync(
start = start,
duration = duration,
points = toPointsGroup(it.drop(1).dropLast(1)).toTypedArray<IntArray>(),
callback = toGestureResultCallback(scriptRuntime, last),
)
} }
else -> scriptRuntime.automator.gestureAsync(start, duration, toPointsGroup(it.drop(1)).toTypedArray<IntArray>()) else -> scriptRuntime.automator.gestureAsync(start, duration, toPointsGroup(it.drop(1)).toTypedArray<IntArray>())
} }
@@ -349,7 +354,10 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
when { when {
isGestureResultCallbackLike(last) -> { isGestureResultCallbackLike(last) -> {
it.dropLast(1).forEach { o -> require((o is List<*>)) { "Arguments for automator.gesturesAsync should be of type Array<Any>" } } it.dropLast(1).forEach { o -> require((o is List<*>)) { "Arguments for automator.gesturesAsync should be of type Array<Any>" } }
scriptRuntime.automator.gesturesAsync(toStrokes(scriptRuntime, it.dropLast(1).toTypedArray<Any?>()), toGestureResultCallback(last)) scriptRuntime.automator.gesturesAsync(
strokes = toStrokes(scriptRuntime, it.dropLast(1).toTypedArray<Any?>()),
callback = toGestureResultCallback(scriptRuntime, last),
)
} }
else -> { else -> {
it.dropLast(1).forEach { o -> require((o is List<*>)) { "Arguments for automator.gesturesAsync should be of type Array<Any>" } } it.dropLast(1).forEach { o -> require((o is List<*>)) { "Arguments for automator.gesturesAsync should be of type Array<Any>" } }
@@ -662,16 +670,16 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
else -> throw WrappedIllegalArgumentException("Invalid arguments length (${args.size}) for \"args\" of Automator#performAction") else -> throw WrappedIllegalArgumentException("Invalid arguments length (${args.size}) for \"args\" of Automator#performAction")
} }
private fun toGestureResultCallback(callback: Any?): AccessibilityService.GestureResultCallback? { private fun toGestureResultCallback(scriptRuntime: ScriptRuntime, callback: Any?): AccessibilityService.GestureResultCallback? {
if (!isGestureResultCallbackLike(callback)) return null if (!isGestureResultCallbackLike(callback)) return null
return object : AccessibilityService.GestureResultCallback() { return object : AccessibilityService.GestureResultCallback() {
override fun onCompleted(gestureDescription: GestureDescription) { override fun onCompleted(gestureDescription: GestureDescription) {
when (callback) { when (callback) {
is BaseFunction -> withRhinoContext { cx -> is BaseFunction -> withRhinoContext(scriptRuntime) { cx ->
callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(true)) callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(true))
} }
is NativeObject -> callback.prop("onCompleted")?.let { is NativeObject -> callback.prop("onCompleted")?.let {
if (it is BaseFunction) withRhinoContext { cx -> if (it is BaseFunction) withRhinoContext(scriptRuntime) { cx ->
it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription)) it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription))
} }
} }
@@ -680,11 +688,11 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override fun onCancelled(gestureDescription: GestureDescription) { override fun onCancelled(gestureDescription: GestureDescription) {
when (callback) { when (callback) {
is BaseFunction -> withRhinoContext { cx -> is BaseFunction -> withRhinoContext(scriptRuntime) { cx ->
callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(false)) callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(false))
} }
is NativeObject -> callback.prop("onCancelled")?.let { is NativeObject -> callback.prop("onCancelled")?.let {
if (it is BaseFunction) withRhinoContext { cx -> if (it is BaseFunction) withRhinoContext(scriptRuntime) { cx ->
it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription)) it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription))
} }
} }

View File

@@ -13,7 +13,7 @@ import org.autojs.autojs.core.inputevent.RootAutomator as CoreRootAutomator
import org.mozilla.javascript.ScriptRuntime as RhinoScriptRuntime import org.mozilla.javascript.ScriptRuntime as RhinoScriptRuntime
@Suppress("unused") @Suppress("unused")
class RootAutomatorNativeObject(scriptRuntime: ScriptRuntime, waitForReady: Any? = false) : NativeObject() { class RootAutomatorNativeObject(private val scriptRuntime: ScriptRuntime, waitForReady: Any? = false) : NativeObject() {
private val mRootAutomatorObject: Scriptable = run { private val mRootAutomatorObject: Scriptable = run {
val rootAutomator = when (waitForReady) { val rootAutomator = when (waitForReady) {
@@ -46,7 +46,7 @@ class RootAutomatorNativeObject(scriptRuntime: ScriptRuntime, waitForReady: Any?
// # 'touchDown', 'touchUp', 'touchMove', 'getDefaultId', 'setDefaultId', 'exit', // # 'touchDown', 'touchUp', 'touchMove', 'getDefaultId', 'setDefaultId', 'exit',
// # ] // # ]
return when (val o = mRootAutomatorObject.prop(name)) { return when (val o = mRootAutomatorObject.prop(name)) {
is BaseFunction -> withRhinoContext { cx -> is BaseFunction -> withRhinoContext(scriptRuntime) { cx ->
BoundFunction(cx, mRootAutomatorObject, o, mRootAutomatorObject, arrayOf()) BoundFunction(cx, mRootAutomatorObject, o, mRootAutomatorObject, arrayOf())
} }
else -> super.get(name, start) else -> super.get(name, start)

View File

@@ -7,15 +7,15 @@ import org.apache.log4j.LogManager
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.core.console.ConsoleImpl import org.autojs.autojs.core.console.ConsoleImpl
import org.autojs.autojs.core.console.ConsoleImpl.Companion.DEFAULT_EXIT_ON_CLOSE_TIMEOUT import org.autojs.autojs.core.console.ConsoleImpl.Companion.DEFAULT_EXIT_ON_CLOSE_TIMEOUT
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.ArgumentGuards import org.autojs.autojs.rhino.ArgumentGuards
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component1 import org.autojs.autojs.rhino.ArgumentGuards.Companion.component1
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component2 import org.autojs.autojs.rhino.ArgumentGuards.Companion.component2
import org.autojs.autojs.rhino.ProxyObject
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.extension.ScriptableExtensions.hasProp import org.autojs.autojs.rhino.extension.ScriptableExtensions.hasProp
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
import org.autojs.autojs.rhino.extension.ScriptableObjectExtensions.inquire import org.autojs.autojs.rhino.extension.ScriptableObjectExtensions.inquire
import org.autojs.autojs.rhino.ProxyObject
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.AugmentableProxy import org.autojs.autojs.runtime.api.augment.AugmentableProxy
import org.autojs.autojs.runtime.api.augment.s13n.S13n import org.autojs.autojs.runtime.api.augment.s13n.S13n
@@ -50,7 +50,7 @@ import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.Undefined import org.mozilla.javascript.Undefined
@Suppress("unused", "UNUSED_PARAMETER") @Suppress("unused", "UNUSED_PARAMETER")
class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) { class Console(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
private val mRtConsole = scriptRuntime.console private val mRtConsole = scriptRuntime.console
private val mTopLevelScope = scriptRuntime.topLevelScope private val mTopLevelScope = scriptRuntime.topLevelScope
@@ -137,7 +137,7 @@ class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
::launch.name to "launchConsole", ::launch.name to "launchConsole",
) )
private fun getStackTrace() = withRhinoContext { cx -> private fun getStackTrace() = withRhinoContext(scriptRuntime) { cx ->
newNativeObject().also { o -> newNativeObject().also { o ->
val globalErrorObject = mTopLevelScope.prop(NativeError.ERROR_TAG) as ScriptableObject val globalErrorObject = mTopLevelScope.prop(NativeError.ERROR_TAG) as ScriptableObject
NativeError.js_captureStackTrace( NativeError.js_captureStackTrace(

View File

@@ -4,6 +4,7 @@ import org.autojs.autojs.annotation.RhinoFunctionBody
import org.autojs.autojs.annotation.RhinoSingletonFunctionInterface import org.autojs.autojs.annotation.RhinoSingletonFunctionInterface
import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.util.RhinoUtils.getOrCreateStandardObjects
import org.autojs.autojs.util.RhinoUtils.withRhinoContext import org.autojs.autojs.util.RhinoUtils.withRhinoContext
import org.mozilla.javascript.Context import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable import org.mozilla.javascript.Scriptable
@@ -61,7 +62,7 @@ object Species : Augmentable(), Invokable {
when { when {
o == null -> "Null" o == null -> "Null"
Undefined.isUndefined(o) -> "Undefined" Undefined.isUndefined(o) -> "Undefined"
else -> when (val obj = withRhinoContext { cx -> Context.javaToJS(o, cx.initStandardObjects()) }) { else -> when (val obj = withRhinoContext { cx -> Context.javaToJS(o, cx.getOrCreateStandardObjects()) }) {
is Boolean -> "Boolean" is Boolean -> "Boolean"
is String -> "String" is String -> "String"
is BigInteger -> "BigInt" is BigInteger -> "BigInt"

View File

@@ -195,7 +195,7 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
uiMapper = { response -> uiMapper = { response ->
// Wrap response into Rhino object on UI thread with Rhino Context. // Wrap response into Rhino object on UI thread with Rhino Context.
// zh-CN: 在 UI 线程进入 Rhino Context, 将 Response 包装为 Rhino 对象. // zh-CN: 在 UI 线程进入 Rhino Context, 将 Response 包装为 Rhino 对象.
withRhinoContext { withRhinoContext(scriptRuntime) {
val wrapped = wrapResponse(scriptRuntime, response, prepared.cacheBody, prepared.cacheThreshold) val wrapped = wrapResponse(scriptRuntime, response, prepared.cacheBody, prepared.cacheThreshold)
// Optional: if user provided callback, call it on UI thread. // Optional: if user provided callback, call it on UI thread.

View File

@@ -9,14 +9,14 @@ import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okio.BufferedSink import okio.BufferedSink
import org.autojs.autojs.pio.PFile
import org.autojs.autojs.pio.PFileInterface
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNumber import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNumber
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsString import org.autojs.autojs.rhino.extension.AnyExtensions.isJsString
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.extension.AnyExtensions.toRuntimePath import org.autojs.autojs.rhino.extension.AnyExtensions.toRuntimePath
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
import org.autojs.autojs.pio.PFile
import org.autojs.autojs.pio.PFileInterface
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.Mime import org.autojs.autojs.runtime.api.Mime
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
@@ -53,7 +53,7 @@ class RequestBuilderHelper(private val options: NativeObject) {
// require(method is String) { "Property method is required for header options" } // require(method is String) { "Property method is required for header options" }
when { when {
!options.prop(Http.KEY_BODY).isJsNullish() -> { !options.prop(Http.KEY_BODY).isJsNullish() -> {
request.method(method, parseBody()) request.method(method, parseBody(scriptRuntime))
} }
!options.prop(Http.KEY_FILES).isJsNullish() -> { !options.prop(Http.KEY_FILES).isJsNullish() -> {
request.method(method, parseMultipart(scriptRuntime)) request.method(method, parseMultipart(scriptRuntime))
@@ -64,7 +64,7 @@ class RequestBuilderHelper(private val options: NativeObject) {
} }
} }
fun parseBody(): RequestBody = when (val body = options.prop(Http.KEY_BODY)) { fun parseBody(scriptRuntime: ScriptRuntime): RequestBody = when (val body = options.prop(Http.KEY_BODY)) {
is RequestBody -> body is RequestBody -> body
is String -> { is String -> {
val mediaType = options.prop(Http.KEY_CONTENT_TYPE).takeUnless { it.isJsNullish() } val mediaType = options.prop(Http.KEY_CONTENT_TYPE).takeUnless { it.isJsNullish() }
@@ -77,7 +77,7 @@ class RequestBuilderHelper(private val options: NativeObject) {
} }
override fun writeTo(sink: BufferedSink) { override fun writeTo(sink: BufferedSink) {
RhinoUtils.withRhinoContext { cx -> RhinoUtils.withRhinoContext(scriptRuntime) { cx ->
body.call(cx, body, body, arrayOf(sink)) body.call(cx, body, body, arrayOf(sink))
} }
} }

View File

@@ -2,12 +2,12 @@ package org.autojs.autojs.runtime.api.augment.http
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.autojs.autojs.annotation.RhinoStandardFunctionInterface import org.autojs.autojs.annotation.RhinoStandardFunctionInterface
import org.autojs.autojs.rhino.extension.AnyExtensions.toRuntimePath import org.autojs.autojs.pio.PFile
import org.autojs.autojs.rhino.ArgumentGuards import org.autojs.autojs.rhino.ArgumentGuards
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component1 import org.autojs.autojs.rhino.ArgumentGuards.Companion.component1
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component2 import org.autojs.autojs.rhino.ArgumentGuards.Companion.component2
import org.autojs.autojs.rhino.extension.AnyExtensions.toRuntimePath
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
import org.autojs.autojs.pio.PFile
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils import org.autojs.autojs.util.RhinoUtils
@@ -56,7 +56,7 @@ class ResponseBodyNativeObject(
return super.get(name, start) return super.get(name, start)
} }
return when (val o = mResBodyObject.prop(name)) { return when (val o = mResBodyObject.prop(name)) {
is BaseFunction -> withRhinoContext { cx -> is BaseFunction -> withRhinoContext(scriptRuntime) { cx ->
BoundFunction(cx, mResBodyObject, o, mResBodyObject, arrayOf()) BoundFunction(cx, mResBodyObject, o, mResBodyObject, arrayOf())
} }
else -> super.get(name, start) else -> super.get(name, start)

View File

@@ -1,6 +1,5 @@
package org.autojs.autojs.runtime.api.augment.jsox package org.autojs.autojs.runtime.api.augment.jsox
import org.autojs.autojs.annotation.RhinoFunctionBody
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.annotation.RhinoRuntimeFunctionWithThisObjInterface import org.autojs.autojs.annotation.RhinoRuntimeFunctionWithThisObjInterface
import org.autojs.autojs.rhino.ArgumentGuards import org.autojs.autojs.rhino.ArgumentGuards
@@ -12,6 +11,7 @@ import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.util.Util.ensureArrayTypeRhino import org.autojs.autojs.runtime.api.augment.util.Util.ensureArrayTypeRhino
import org.autojs.autojs.util.ArrayUtils.unshiftWith import org.autojs.autojs.util.ArrayUtils.unshiftWith
import org.autojs.autojs.util.RhinoUtils.callFunction
import org.autojs.autojs.util.RhinoUtils.coerceArray import org.autojs.autojs.util.RhinoUtils.coerceArray
import org.autojs.autojs.util.RhinoUtils.coerceFunction import org.autojs.autojs.util.RhinoUtils.coerceFunction
import org.autojs.autojs.util.RhinoUtils.undefined import org.autojs.autojs.util.RhinoUtils.undefined
@@ -158,18 +158,14 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun distinctBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { fun distinctBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { argList ->
distinctByRhino(it) withRhinoContext(scriptRuntime) { cx ->
} val (arrRaw, selector) = argList
val arr = coerceArray(arrRaw)
@JvmStatic arr.distinctBy { ele ->
@RhinoFunctionBody callFunction(scriptRuntime, coerceFunction(selector), arr, arr, arrayOf(ele))
fun distinctByRhino(it: Array<Any?>): NativeArray = withRhinoContext { cx -> }.toNativeArray()
val (arr, selector) = it }
coerceArray(arr).distinctBy { ele ->
require(arr is NativeArray)
coerceFunction(selector).call(cx, arr, arr, arrayOf(ele))
}.toNativeArray()
} }
@JvmStatic @JvmStatic
@@ -202,148 +198,116 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { fun sortBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { argList ->
val (arr, selector) = it val (arr, selector) = argList
sortByRhino(arr, selector) withRhinoContext(scriptRuntime) { cx ->
} require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortBy must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortBy must be a JavaScript Function" }
@JvmStatic when {
@RhinoFunctionBody arr.length < 2 -> arr
fun sortByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx -> else -> {
require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortBy must be a JavaScript Array" } // In-place sorting (zh-CN: 原地排序)
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortBy must be a JavaScript Function" } NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionAsc(selector)))
when { arr
arr.length < 2 -> arr }
else -> {
// In-place sorting (zh-CN: 原地排序)
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionAsc(selector)))
arr
} }
} }
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortByDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { fun sortByDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { argList ->
val (arr, selector) = it val (arr, selector) = argList
sortByDescendingRhino(arr, selector) withRhinoContext(scriptRuntime) { cx ->
} require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortByDescending must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortByDescending must be a JavaScript Function" }
@JvmStatic when {
@RhinoFunctionBody arr.length < 2 -> arr
fun sortByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx -> else -> {
require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortByDescending must be a JavaScript Array" } // In-place sorting (zh-CN: 原地排序)
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortByDescending must be a JavaScript Function" } NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionDesc(selector)))
when { arr
arr.length < 2 -> arr }
else -> {
// In-place sorting (zh-CN: 原地排序)
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionDesc(selector)))
arr
} }
} }
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { fun sortDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { o ->
sortDescendingRhino(it) withRhinoContext(scriptRuntime) { cx ->
} require(o is NativeArray) { "Argument \"arr\" ${o.jsBrief()} for Arrayx.sortDescending must be a JavaScript Array" }
NativeArray.js_sort(cx, o, o, arrayOf(toCompareFunctionDesc()))
@JvmStatic o
@RhinoFunctionBody }
fun sortDescendingRhino(arr: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortDescending must be a JavaScript Array" }
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionDesc()))
arr
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sorted(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { fun sorted(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { o ->
sortedRhino(it) withRhinoContext(scriptRuntime) { cx ->
} require(o is NativeArray) { "Argument \"arr\" ${o.jsBrief()} for Arrayx.sorted must be a JavaScript Array" }
val copied = o.slice(o.indices).toNativeArray()
@JvmStatic NativeArray.js_sort(cx, o, copied, arrayOf(toCompareFunctionAsc()))
@RhinoFunctionBody copied
fun sortedRhino(it: Any?): NativeArray = withRhinoContext { cx -> }
require(it is NativeArray) { "Argument \"arr\" ${it.jsBrief()} for Arrayx.sorted must be a JavaScript Array" }
val copied = it.slice(it.indices).toNativeArray()
NativeArray.js_sort(cx, it, copied, arrayOf(toCompareFunctionAsc()))
copied
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortedDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { fun sortedDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { o ->
sortedDescendingRhino(it) withRhinoContext(scriptRuntime) { cx ->
} require(o is NativeArray) { "Argument \"arr\" ${o.jsBrief()} for Arrayx.sortedDescending must be a JavaScript Array" }
val copied = o.slice(o.indices).toNativeArray()
@JvmStatic NativeArray.js_sort(cx, o, copied, arrayOf(toCompareFunctionDesc()))
@RhinoFunctionBody copied
fun sortedDescendingRhino(it: Any?): NativeArray = withRhinoContext { cx -> }
require(it is NativeArray) { "Argument \"arr\" ${it.jsBrief()} for Arrayx.sortedDescending must be a JavaScript Array" }
val copied = it.slice(it.indices).toNativeArray()
NativeArray.js_sort(cx, it, copied, arrayOf(toCompareFunctionDesc()))
copied
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortedBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { fun sortedBy(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { argList ->
val (arr, selector) = it val (arr, selector) = argList
sortedByRhino(arr, selector) withRhinoContext(scriptRuntime) { cx ->
} require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortedBy must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortedBy must be a JavaScript Function" }
@JvmStatic val copied = arr.slice(arr.indices).toNativeArray()
@RhinoFunctionBody when {
fun sortedByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx -> arr.length < 2 -> copied
require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortedBy must be a JavaScript Array" } else -> {
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortedBy must be a JavaScript Function" } NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionAsc(selector)))
val copied = arr.slice(arr.indices).toNativeArray() copied
when { }
arr.length < 2 -> copied
else -> {
NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionAsc(selector)))
copied
} }
} }
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun sortedByDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { fun sortedByDescending(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLength(args, 2) { argList ->
val (arr, selector) = it val (arr, selector) = argList
sortedByDescendingRhino(arr, selector) withRhinoContext(scriptRuntime) { cx ->
} require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortedByDescending must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortedByDescending must be a JavaScript Function" }
@JvmStatic val copied = arr.slice(arr.indices).toNativeArray()
@RhinoFunctionBody when {
fun sortedByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx -> arr.length < 2 -> copied
require(arr is NativeArray) { "Argument \"arr\" ${arr.jsBrief()} for Arrayx.sortedByDescending must be a JavaScript Array" } else -> {
require(selector is BaseFunction) { "Argument \"selector\" ${selector.jsBrief()} for Arrayx.sortedByDescending must be a JavaScript Function" } NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionDesc(selector)))
val copied = arr.slice(arr.indices).toNativeArray() copied
when { }
arr.length < 2 -> copied
else -> {
NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionDesc(selector)))
copied
} }
} }
} }
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun shuffle(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { fun shuffle(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsOnlyOne(args) { o ->
shuffleRhino(it) withRhinoContext(scriptRuntime) { cx ->
} require(o is NativeArray) { "Argument \"arr\" ${o.jsBrief()} for Arrayx.shuffle must be a JavaScript Array" }
NativeArray.js_sort(cx, o, o, arrayOf(toCompareFunctionRandom()))
@JvmStatic o
@RhinoFunctionBody }
fun shuffleRhino(it: Any?): NativeArray = withRhinoContext { cx ->
require(it is NativeArray) { "Argument \"arr\" ${it.jsBrief()} for Arrayx.shuffle must be a JavaScript Array" }
NativeArray.js_sort(cx, it, it, arrayOf(toCompareFunctionRandom()))
it
} }
private fun toCompareFunctionAsc(selector: BaseFunction) = object : BaseFunction() { private fun toCompareFunctionAsc(selector: BaseFunction) = object : BaseFunction() {

View File

@@ -56,7 +56,7 @@ class Selector(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
// @Hint by SuperMonster003 on Jul 25, 2024. // @Hint by SuperMonster003 on Jul 25, 2024.
// ! For scope binding. // ! For scope binding.
// ! zh-CN: 用于绑定作用域. // ! zh-CN: 用于绑定作用域.
withRhinoContext { cx -> withRhinoContext(scriptRuntime) { cx ->
global.defineProp(methodName, newBaseFunction(null, { argList -> global.defineProp(methodName, newBaseFunction(null, { argList ->
val methodKey = coerceString(argList[0]) val methodKey = coerceString(argList[0])
newBaseFunction(methodKey, { arguments -> newBaseFunction(methodKey, { arguments ->

View File

@@ -232,7 +232,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
val widgets = scriptRuntime.ui.widgets val widgets = scriptRuntime.ui.widgets
if (widgets.contains(viewName)) { if (widgets.contains(viewName)) {
val ctor = widgets.prop(viewName) as BaseFunction val ctor = widgets.prop(viewName) as BaseFunction
val widget = withRhinoContext { cx -> val widget = withRhinoContext(scriptRuntime) { cx ->
ctor.construct(cx, scriptRuntime.topLevelScope, arrayOf()) ctor.construct(cx, scriptRuntime.topLevelScope, arrayOf())
} as ScriptableObject } as ScriptableObject
val f = widget.prop("renderInternal") as BaseFunction val f = widget.prop("renderInternal") as BaseFunction
@@ -881,7 +881,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
} }
} }
}, NOT_CONSTRUCTABLE) }, NOT_CONSTRUCTABLE)
withRhinoContext { cx -> withRhinoContext(scriptRuntime) { cx ->
arrayObserveFunc.call(cx, global, globalArray, arrayOf(dataSource, handlerFunc)) arrayObserveFunc.call(cx, global, globalArray, arrayOf(dataSource, handlerFunc))
} }
} }
@@ -899,7 +899,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
isAutoJsUiMode -> { isAutoJsUiMode -> {
callFunction(scriptRuntime, action, scriptRuntime.topLevelScope, arrayOf()) callFunction(scriptRuntime, action, scriptRuntime.topLevelScope, arrayOf())
} }
else -> withRhinoContext { cx -> else -> withRhinoContext(scriptRuntime) { cx ->
val scope = scriptRuntime.topLevelScope val scope = scriptRuntime.topLevelScope
val exitIfErrorFunc = scope.prop("__exitIfError__") as BaseFunction val exitIfErrorFunc = scope.prop("__exitIfError__") as BaseFunction
exitIfErrorFunc.call(cx, scope, scope, arrayOf(newBaseFunction("action", { exitIfErrorFunc.call(cx, scope, scope, arrayOf(newBaseFunction("action", {

View File

@@ -35,7 +35,7 @@ class Web(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic @JvmStatic
@RhinoFunctionBody @RhinoFunctionBody
fun newInjectableWebViewRhinoWithRuntime(scriptRuntime: ScriptRuntime, vararg args: Any?): InjectableWebView = withRhinoContext { cx -> fun newInjectableWebViewRhinoWithRuntime(scriptRuntime: ScriptRuntime, vararg args: Any?): InjectableWebView = withRhinoContext(scriptRuntime) { cx ->
when (args.size) { when (args.size) {
2 -> { 2 -> {
val (androidContext, url) = args val (androidContext, url) = args
@@ -60,7 +60,7 @@ class Web(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic @JvmStatic
@RhinoRuntimeFunctionInterface @RhinoRuntimeFunctionInterface
fun newInjectableWebClient(scriptRuntime: ScriptRuntime, args: Array<out Any?>): InjectableWebClient = ensureArgumentsIsEmpty(args) { fun newInjectableWebClient(scriptRuntime: ScriptRuntime, args: Array<out Any?>): InjectableWebClient = ensureArgumentsIsEmpty(args) {
withRhinoContext { cx -> InjectableWebClient(cx, scriptRuntime.topLevelScope) } withRhinoContext(scriptRuntime) { cx -> InjectableWebClient(cx, scriptRuntime.topLevelScope) }
} }
@JvmStatic @JvmStatic

View File

@@ -9,6 +9,7 @@ import android.os.Parcelable
import org.autojs.autojs.AutoJs import org.autojs.autojs.AutoJs
import org.autojs.autojs.annotation.RhinoStandardFunctionInterface import org.autojs.autojs.annotation.RhinoStandardFunctionInterface
import org.autojs.autojs.core.automator.UiObjectCollection import org.autojs.autojs.core.automator.UiObjectCollection
import org.autojs.autojs.engine.RhinoJavaScriptEngine
import org.autojs.autojs.rhino.TopLevelScope import org.autojs.autojs.rhino.TopLevelScope
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
@@ -95,13 +96,28 @@ object RhinoUtils {
private val TAG = RhinoUtils::class.java.simpleName private val TAG = RhinoUtils::class.java.simpleName
private val STANDARD_OBJECTS_KEY = Any()
@JvmStatic @JvmStatic
val UNDEFINED = Undefined.instance as Undefined val UNDEFINED = Undefined.instance as Undefined
@JvmStatic
fun Context.getOrCreateStandardObjects(): ScriptableObject {
// Cache standard objects per Context to avoid repeated initStandardObjects().
// zh-CN: 按 Context 缓存标准对象, 避免重复调用 initStandardObjects().
val cached = this.getThreadLocal(STANDARD_OBJECTS_KEY) as? ScriptableObject
if (cached != null) return cached
return this.initStandardObjects().also { created ->
this.putThreadLocal(STANDARD_OBJECTS_KEY, created)
}
}
@JvmStatic @JvmStatic
val standardObjects: ScriptableObject by lazy { val standardObjects: ScriptableObject by lazy {
// Create a global singleton standard objects as a low-fidelity fallback.
// zh-CN: 创建全局单例标准对象, 用作低保真兜底.
try { try {
Context.enter().initStandardObjects() Context.enter().getOrCreateStandardObjects()
} finally { } finally {
Context.exit() Context.exit()
} }
@@ -125,33 +141,25 @@ object RhinoUtils {
} }
@JvmStatic @JvmStatic
fun callGlobalFunction(name: String, paramsToFunction: Array<Any?>): Any? { fun callToStringFunction(o: Scriptable): String =
return callGlobalFunction(null, name, paramsToFunction) Context.toString(callFunction(o, "toString", arrayOf()))
}
@JvmStatic @JvmStatic
fun callGlobalFunction(scriptRuntime: ScriptRuntime?, name: String, paramsToFunction: Array<Any?>) = withRhinoContext { cx -> fun callToStringFunction(scriptRuntime: ScriptRuntime, o: Scriptable): String =
val topLevel = ImporterTopLevel(cx) Context.toString(callFunction(scriptRuntime, o, "toString", arrayOf()))
callFunction(scriptRuntime, topLevel, name, paramsToFunction)
}
@JvmStatic
fun callToStringFunction(o: Scriptable): String {
return callToStringFunction(null, o)
}
@JvmStatic
fun callToStringFunction(scriptRuntime: ScriptRuntime?, o: Scriptable): String = Context.toString(callFunction(scriptRuntime, o, "toString", arrayOf()))
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(obj: Scriptable, name: String, paramsToFunction: Array<Any?>): Any? { fun callFunction(obj: Scriptable, name: String, paramsToFunction: Array<Any?>): Any? {
return callFunction(null, obj, name, paramsToFunction) val property = obj.prop(name)
if (property == NOT_FOUND) throw IllegalArgumentException("Property $name not found on $obj")
if (property !is BaseFunction) throw IllegalArgumentException("Property $name on $obj must be a BaseFunction instead of ${property.jsBrief()}")
return callFunction(property, obj, obj, paramsToFunction)
} }
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(scriptRuntime: ScriptRuntime?, obj: Scriptable, name: String, paramsToFunction: Array<Any?>): Any? { fun callFunction(scriptRuntime: ScriptRuntime, obj: Scriptable, name: String, paramsToFunction: Array<Any?>): Any? {
val property = obj.prop(name) val property = obj.prop(name)
if (property == NOT_FOUND) throw IllegalArgumentException("Property $name not found on $obj") if (property == NOT_FOUND) throw IllegalArgumentException("Property $name not found on $obj")
if (property !is BaseFunction) throw IllegalArgumentException("Property $name on $obj must be a BaseFunction instead of ${property.jsBrief()}") if (property !is BaseFunction) throw IllegalArgumentException("Property $name on $obj must be a BaseFunction instead of ${property.jsBrief()}")
@@ -160,38 +168,40 @@ object RhinoUtils {
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(func: BaseFunction, paramsToFunction: Array<Any?>): Any? { fun callFunction(func: BaseFunction, paramsToFunction: Array<Any?>): Any? =
return callFunction(null, func, paramsToFunction) callFunction(func, null, paramsToFunction)
}
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(scriptRuntime: ScriptRuntime?, func: BaseFunction, paramsToFunction: Array<Any?>): Any? { fun callFunction(scriptRuntime: ScriptRuntime, func: BaseFunction, paramsToFunction: Array<Any?>): Any? =
return callFunction(scriptRuntime, func, null, paramsToFunction) callFunction(scriptRuntime, func, null, paramsToFunction)
}
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(func: BaseFunction, scope: Scriptable?, args: Array<Any?>): Any? { fun callFunction(func: BaseFunction, scope: Scriptable?, args: Array<Any?>): Any? =
return callFunction(null, func, scope, args) callFunction(func, scope, scope, args)
}
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(scriptRuntime: ScriptRuntime?, func: BaseFunction, scope: Scriptable?, args: Array<Any?>): Any? { fun callFunction(scriptRuntime: ScriptRuntime, func: BaseFunction, scope: Scriptable?, args: Array<Any?>): Any? =
return callFunction(scriptRuntime, func, scope, scope, args) callFunction(scriptRuntime, func, scope, scope, args)
}
@JvmStatic @JvmStatic
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class) @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(func: BaseFunction, scope: Scriptable?, thisObj: Scriptable?, args: Array<Any?>): Any? { fun callFunction(func: BaseFunction, scope: Scriptable?, thisObj: Scriptable?, args: Array<Any?>): Any? =
return callFunction(null, func, scope, thisObj, args) callFunction(null, func, scope, thisObj, args)
}
@JvmStatic @JvmStatic
fun callFunction(scriptRuntime: ScriptRuntime?, func: BaseFunction, scope: Scriptable?, thisObj: Scriptable?, args: Array<Any?>): Any? = withRhinoContext { cx -> fun callFunction(scriptRuntime: ScriptRuntime?, func: BaseFunction, scope: Scriptable?, thisObj: Scriptable?, args: Array<Any?>): Any? = withRhinoContext(scriptRuntime) { cx ->
try { try {
val niceScope = scope ?: cx.initStandardObjects() // Prefer an existing scope to avoid repeatedly creating standard objects.
// zh-CN: 优先使用已有的作用域, 避免反复创建标准对象.
val niceScope = when {
scope != null -> scope
func.parentScope != null -> func.parentScope
scriptRuntime != null -> scriptRuntime.topLevelScope
else -> ImporterTopLevel(cx)
}
when { when {
RhinoScriptRuntime.hasTopCall(cx) -> func.call(cx, niceScope, thisObj, args) RhinoScriptRuntime.hasTopCall(cx) -> func.call(cx, niceScope, thisObj, args)
else -> RhinoScriptRuntime.doTopCall(func, cx, niceScope, thisObj, args, false) else -> RhinoScriptRuntime.doTopCall(func, cx, niceScope, thisObj, args, false)
@@ -369,28 +379,23 @@ object RhinoUtils {
} }
@JvmStatic @JvmStatic
fun encodeURI(str: String): String = encodeURI(null, str) fun encodeURI(scriptRuntime: ScriptRuntime, str: String): String =
Context.toString(callGlobalFunction(scriptRuntime, "encodeURI", arrayOf(str)))
@JvmStatic @JvmStatic
fun encodeURI(scriptRuntime: ScriptRuntime?, str: String): String = Context.toString(callGlobalFunction(scriptRuntime, "encodeURI", arrayOf(str))) fun parseInt(scriptRuntime: ScriptRuntime, str: String?): Double =
Context.toNumber(callGlobalFunction(scriptRuntime, "parseInt", arrayOf(str)))
@JvmStatic @JvmStatic
fun parseInt(str: String?): Double = parseInt(null, str) fun parseInt(scriptRuntime: ScriptRuntime, str: String?, radix: Number): Double =
Context.toNumber(callGlobalFunction(scriptRuntime, "parseInt", arrayOf(str, radix.toDouble())))
@JvmStatic @JvmStatic
fun parseInt(scriptRuntime: ScriptRuntime?, str: String?): Double = Context.toNumber(callGlobalFunction(scriptRuntime, "parseInt", arrayOf(str))) fun parseFloat(scriptRuntime: ScriptRuntime, str: String?): Double =
Context.toNumber(callGlobalFunction(scriptRuntime, "parseFloat", arrayOf(str)))
@JvmStatic private fun callGlobalFunction(scriptRuntime: ScriptRuntime, name: String, paramsToFunction: Array<Any?>) =
fun parseInt(str: String?, radix: Number): Double = parseInt(null, str, radix) callFunction(scriptRuntime, scriptRuntime.topLevelScope, name, paramsToFunction)
@JvmStatic
fun parseInt(scriptRuntime: ScriptRuntime?, str: String?, radix: Number): Double = Context.toNumber(callGlobalFunction(scriptRuntime, "parseInt", arrayOf(str, radix.toDouble())))
@JvmStatic
fun parseFloat(str: String?): Double = parseFloat(null, str)
@JvmStatic
fun parseFloat(scriptRuntime: ScriptRuntime?, str: String?): Double = Context.toNumber(callGlobalFunction(scriptRuntime, "parseFloat", arrayOf(str)))
@JvmStatic @JvmStatic
fun ensureNativeArrayLength(o: NativeArray, length: Int, desc: String) { fun ensureNativeArrayLength(o: NativeArray, length: Int, desc: String) {
@@ -417,7 +422,8 @@ object RhinoUtils {
@JvmStatic @JvmStatic
fun runJavaScript(code: String): Any? = withRhinoContext { cx -> fun runJavaScript(code: String): Any? = withRhinoContext { cx ->
cx.evaluateString(standardObjects, code, null, 1, null) val scope = cx.getOrCreateStandardObjects()
cx.evaluateString(scope, code, null, 1, null)
} }
@JvmStatic @JvmStatic
@@ -466,13 +472,7 @@ object RhinoUtils {
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun coerceRunnable(o: Any?, def: Runnable? = null): Runnable { fun coerceRunnable(scriptRuntime: ScriptRuntime, o: Any?, def: Runnable? = null): Runnable = when {
return coerceRunnable(null, o, def)
}
@JvmStatic
@JvmOverloads
fun coerceRunnable(scriptRuntime: ScriptRuntime?, o: Any?, def: Runnable? = null): Runnable = when {
!o.isJsNullish() -> when (o) { !o.isJsNullish() -> when (o) {
is BaseFunction -> Runnable { callFunction(scriptRuntime, o, arrayOf()) } is BaseFunction -> Runnable { callFunction(scriptRuntime, o, arrayOf()) }
is Runnable -> o is Runnable -> o
@@ -789,16 +789,32 @@ object RhinoUtils {
RhinoScriptRuntime.evalSpecial(cx, global, global, arrayOf(s), "eval code", 1) RhinoScriptRuntime.evalSpecial(cx, global, global, arrayOf(s), "eval code", 1)
} }
fun <R> withRhinoContext(function: (context: Context) -> R): R { @JvmStatic
@JvmOverloads
fun <R> withRhinoContext(scriptRuntime: ScriptRuntime? = null, function: (context: Context) -> R): R {
var cxRhino: Context? = null var cxRhino: Context? = null
return try { return try {
val cx = Context.getCurrentContext() val cx = Context.getCurrentContext()
?: Context.enter().also { ?: when (scriptRuntime) {
it.initStandardObjects() null -> {
cxRhino = it // This fallback Context.enter() does NOT guarantee WrapFactory from RhinoJavaScriptEngine.
} // zh-CN: 这个兜底的 Context.enter() 无法保证使用 RhinoJavaScriptEngine 的 WrapFactory.
cx.languageVersion = Context.VERSION_ES6 Context.enter()
cx.isInterpretedMode = true }
else -> {
// Enter Rhino Context via engine's ContextFactory to keep WrapFactory and AutoJsContext bindings effective.
// zh-CN: 通过引擎的 ContextFactory 进入 Rhino Context, 以保持 WrapFactory 和 AutoJsContext 绑定生效.
val engine = scriptRuntime.engines.myEngine()
require(engine is RhinoJavaScriptEngine) {
"Current engine ${engine.javaClass.name} is not a RhinoJavaScriptEngine"
}
engine.enterContext()
}
}.apply {
languageVersion = Context.VERSION_ES6
isInterpretedMode = true
}.also { cxRhino = it }
function.invoke(cx) function.invoke(cx)
} finally { } finally {
cxRhino?.let { Context.exit() } cxRhino?.let { Context.exit() }
@@ -870,14 +886,6 @@ object RhinoUtils {
@JvmStatic @JvmStatic
fun initNativeObjectPrototype(o: NativeObject): NativeObject { fun initNativeObjectPrototype(o: NativeObject): NativeObject {
// val cx = ContextWrapper.getCurrentContext()
// try {
// val tmpScope: Scriptable = cx.initStandardObjects()
// NativeObject.init(tmpScope, false)
// o.prototype = tmpScope.get("Object", tmpScope) as Scriptable
// } finally {
// Context.exit()
// }
return o.apply { prototype = objectPrototype } return o.apply { prototype = objectPrototype }
} }

View File

@@ -1,5 +1,5 @@
#Fri Jan 30 20:56:33 CST 2026 #Sat Jan 31 15:04:03 CST 2026
BUILD_TIME=1769777793096 BUILD_TIME=1769843043403
COMPILE_SDK_VERSION=36 COMPILE_SDK_VERSION=36
IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125 IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=36 TARGET_SDK_VERSION=36
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3673 VERSION_BUILD=3678
VERSION_NAME=6.7.0 Alpha18 VERSION_NAME=6.7.0 Alpha19
VSCODE_EXT_REQUIRED_VERSION=1.0.13 VSCODE_EXT_REQUIRED_VERSION=1.0.13