6.7.0 - Alpha6 - console.log 等方法打印全局对象 (images, app, ocr 等) 时支持显示详细信息

This commit is contained in:
SuperMonster003
2025-10-05 13:29:04 +08:00
parent 9dd55a063d
commit 4235ffda82
26 changed files with 221 additions and 76 deletions

View File

@@ -19,7 +19,11 @@ plugins {
idea {
module {
excludeDirs.add(file("$rootDir/app/src/main/java/com/stardust/"))
excludeDirs.addAll(listOf(
file("$rootDir/app/src/main/java/com/stardust/"),
file("$rootDir/app/src/main/assets/modules/obsolete/"),
file("$rootDir/app/src/main/assets-app/js-beautify/"),
))
}
}

View File

@@ -30,7 +30,9 @@ import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.Script
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject.DONTENUM
import org.mozilla.javascript.ScriptableObject.PERMANENT
import org.mozilla.javascript.ScriptableObject.READONLY
import org.mozilla.javascript.commonjs.module.RequireBuilder
import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider
import java.io.File
@@ -103,7 +105,7 @@ open class RhinoJavaScriptEngine(private val androidContext: android.content.Con
override fun init() {
thread = Thread.currentThread()
scriptable.defineProp("__engine__", this)
scriptable.defineProp("__engine__", this, READONLY or DONTENUM or PERMANENT)
initRequireBuilder(context, scriptable)
runtime.withTimeConsuming("runtime-init-prologue") {

View File

@@ -24,7 +24,7 @@ class ShizukuPermission(override val context: Context) : PermissionItemHelper {
} catch (e: Throwable) {
e.printStackTrace()
}
WrappedShizuku.config(context, true)?.let { true }
WrappedShizuku.configWithContext(context, true)?.let { true }
?: ViewUtils.showToast(context, R.string.error_failed_to_grant_shizuku_access).let { false }
}
}
@@ -34,7 +34,7 @@ class ShizukuPermission(override val context: Context) : PermissionItemHelper {
return when {
!WrappedShizuku.isInstalled(context) -> false.also { ViewUtils.showToast(context, R.string.error_shizuku_is_not_installed) }
Shizuku.isPreV11() -> false.also { ViewUtils.showToast(context, R.string.error_shizuku_version_is_not_supported) }
else -> WrappedShizuku.config(context, false)?.let { true }
else -> WrappedShizuku.configWithContext(context, false)?.let { true }
?: ViewUtils.showToast(context, R.string.error_failed_to_revoke_shizuku_access).let { false }
}
}

View File

@@ -73,6 +73,12 @@ open class ProxyObject() : NativeObject() {
@JvmField
val PROXY_OBJECT_KEY = "__proxy__"
@JvmField
val AUGMENTED_OBJECT_KEY = "__augmented__"
@JvmField
val AUGMENTED_CUSTOM_TO_STRING_KEY = "__augmented_custom_to_string__"
@JvmField
val PROXY_SETTER_KEY = "set"

View File

@@ -458,7 +458,7 @@ class ScriptRuntime private constructor(builder: Builder) {
floaty = ApiFloaty(uiHandler, this)
ui = ApiUI(mUiHandlerAppContext, this)
util = ApiUtil(mUiHandlerAppContext, this)
util = ApiUtil
images = ApiImages(mUiHandlerAppContext, this)
device = ApiDevice(mUiHandlerAppContext)
media = ApiMedia(mUiHandlerAppContext, this)

View File

@@ -1,9 +1,8 @@
package org.autojs.autojs.runtime.api
import org.autojs.autojs.extension.AnyExtensions.jsBrief
import org.autojs.autojs.runtime.ScriptRuntime
class Util(private val context: android.content.Context, private val scriptRuntime: ScriptRuntime) {
object Util {
fun `class`(o: Any?) = getClassInternal(o, "class")

View File

@@ -120,7 +120,6 @@ object WrappedShizuku {
false.also { if (e.message?.contains(Regex("binder .+n[o']t been received", RegexOption.IGNORE_CASE)) == false) e.printStackTrace() }
}
@JvmStatic
@ScriptInterface
fun isOperational(): Boolean = isRunning() && hasPermission()
@@ -130,12 +129,11 @@ object WrappedShizuku {
@ScriptInterface
fun requestPermission() = Shizuku.requestPermission(mRequestCode)
@ScriptInterface
fun config(isRequest: Boolean?) = config(GlobalAppContext.get(), isRequest)
@ScriptInterface
@JvmOverloads
fun config(context: Context, isRequest: Boolean? = null): Intent? = getLaunchIntent(context)?.also {
fun config(isRequest: Boolean? = null) = configWithContext(GlobalAppContext.get(), isRequest)
fun configWithContext(context: Context, isRequest: Boolean? = null): Intent? = getLaunchIntent(context)?.also {
context.startActivity(it)
val message = when (isRequest) {
true -> "${context.getString(R.string.text_grant_autojs6_access_in_shizuku_app)} (${context.getString(R.string.text_shizuku_service_may_need_to_be_run_first)})"

View File

@@ -5,9 +5,11 @@ import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.extension.AnyExtensions.jsBrief
import org.autojs.autojs.extension.FlexibleArray
import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.rhino.ProxyObject
import org.autojs.autojs.rhino.ProxyObject.Companion.AUGMENTED_CUSTOM_TO_STRING_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_GETTER_KEY
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.events.Events
@@ -118,8 +120,9 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
/**
* List element cases: <br>
* - <1> - name to getter
* - <2> - name to getter to attributes
*/
open val selfAssignmentGetters = listOf<Pair<String, Supplier<Any?>>>()
open val selfAssignmentGetters = listOf<Any>()
/**
* List element cases: <br>
@@ -264,17 +267,19 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
objProtoList += Events.__asEmitter__(scriptRuntime, emptyArray())
}
objProtoList.forEachIndexed { index, prototypeObject -> augmentPrototypesAt(index, newObj, prototypeObject) }
scopeProtoList.forEachIndexed { index, prototypeObject -> augmentPrototypesAt(index, global, prototypeObject) }
val newObjOriginalPrototype = newObj.prototype
objProtoList.forEachIndexed { index, prototypeObject -> augmentPrototypesAt(index, newObj, prototypeObject, newObjOriginalPrototype) }
val globalOriginalPrototype = global.prototype
scopeProtoList.forEachIndexed { index, prototypeObject -> augmentPrototypesAt(index, global, prototypeObject, globalOriginalPrototype) }
}
private fun augmentPrototypesAt(index: Int, o: ScriptableObject, proto: Scriptable) {
private fun augmentPrototypesAt(index: Int, o: ScriptableObject, proto: Scriptable, originalProto: Scriptable?) {
when (index) {
0 -> o.prototype = proto
1 -> o.prototype.prototype = proto
2 -> o.prototype.prototype.prototype = proto
3 -> o.prototype.prototype.prototype.prototype = proto
4 -> o.prototype.prototype.prototype.prototype.prototype = proto
0 -> o.prototype = proto.apply { prototype = originalProto }
1 -> o.prototype.prototype = proto.apply { prototype = originalProto }
2 -> o.prototype.prototype.prototype = proto.apply { prototype = originalProto }
3 -> o.prototype.prototype.prototype.prototype = proto.apply { prototype = originalProto }
4 -> o.prototype.prototype.prototype.prototype.prototype = proto.apply { prototype = originalProto }
else -> throw RuntimeException("Augmentation can only be applied to no more than $index targets")
}
}
@@ -372,6 +377,9 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
if (flag and AS_GLOBAL != 0) {
globalFunctions += name to alias to (PERMANENT or refineAttributes(flag))
}
if (flag and AS_FUNCTIONAL_TO_STRING != 0) {
targetFunctions += AUGMENTED_CUSTOM_TO_STRING_KEY to AUGMENTED_CUSTOM_TO_STRING_KEY to (DONTENUM or PERMANENT or refineAttributes(flag))
}
}
}
else -> throw WrappedIllegalArgumentException("Unknown function element ${item.jsBrief()} for selfAssignmentFunctions")
@@ -381,8 +389,7 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
when (item) {
is String -> globalFunctions += item to item to PERMANENT
is Pair<*, *> -> {
val first = item.first
val second = item.second
val (first, second) = item
val name: String
val aliasList = mutableListOf<String>()
var flag = 0
@@ -474,33 +481,62 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
throw WrappedRuntimeException(niceMessage)
}
}, NOT_CONSTRUCTABLE)
destination.defineProperty(funcNameAlias, f, attributes)
destination.defineWith(funcNameAlias, f, attributes)
}
}
@Suppress("UnnecessaryVariable", "UNCHECKED_CAST")
private fun augmentGettersAndSetters(target: ScriptableObject, global: ScriptableObject) {
selfAssignmentGetters.forEach { pair ->
val (name, getter) = pair
target.defineProperty(name, getter, null, PERMANENT)
selfAssignmentGetters.forEach { item ->
when (item) {
is Pair<*, *> -> {
val (first, second) = item
when (first) {
is String -> {
val name = first
when (val getter = second) {
is Supplier<*> -> {
target.defineWith(name, getter as Supplier<Any?>, null, PERMANENT)
}
else -> throw WrappedIllegalArgumentException("Unknown second element ${second.jsBrief()} for selfAssignmentGetters")
}
}
is Pair<*, *> -> {
val (name, getter) = first
require(name is String) {
throw WrappedIllegalArgumentException("First element of pair must be a String for selfAssignmentGetters")
}
when (val attributes = second) {
is Int -> {
target.defineWith(name, getter as Supplier<Any?>, null, refineAttributes(attributes))
}
else -> throw WrappedIllegalArgumentException("Unknown second element ${second.jsBrief()} for selfAssignmentGetters")
}
}
else -> throw WrappedIllegalArgumentException("Unknown item ${item.jsBrief()} for selfAssignmentGetters")
}
}
else -> throw WrappedIllegalArgumentException("Unknown item ${item.jsBrief()} for selfAssignmentGetters")
}
}
selfAssignmentGettersAndSetters.forEach { triple ->
val (name, getter, setter) = triple
target.defineProperty(name, getter, setter, PERMANENT)
target.defineWith(name, getter, setter, PERMANENT)
}
globalAssignmentGetters.forEach { pair ->
val (name, getter) = pair
global.defineProperty(name, getter, null, PERMANENT)
global.defineWith(name, getter, null, PERMANENT)
}
}
private fun augmentJavaClasses(target: ScriptableObject, global: ScriptableObject) {
selfAssignmentJavaClasses.forEach { pair ->
val (name, clazz) = pair
target.defineProperty(name, NativeJavaClass(global, clazz.java), PERMANENT)
target.defineWith(name, NativeJavaClass(global, clazz.java), PERMANENT)
}
globalAssignmentJavaClasses.forEach { pair ->
val (name, clazz) = pair
global.defineProperty(name, NativeJavaClass(global, clazz.java), PERMANENT)
global.defineWith(name, NativeJavaClass(global, clazz.java), PERMANENT)
}
}
@@ -512,14 +548,44 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
companion object : FlexibleArray() {
const val AS_GLOBAL = 0x1000
const val AS_IGNORED = 0x2000
// @Caution by SuperMonster003 on Oct 5, 2025.
// ! These constants are "bit flags", each value is a power of 2, with only one bit being 1 in binary.
// ! They can be combined using `bitwise OR (|)` and checked using `bitwise AND (&)` without interference.
// ! Do not modify them to the form 0x0101/0x0102/0x0103/0x0104/...,
// ! to avoid flag overlap causing combination and detection logic to fail,
// ! e.g. `flags & AS_GLOBAL` may give false results.
// ! zh-CN:
// ! 这些常量是 "位标志" (bit flags), 每个值都是二的幂, 二进制中仅有一位为 1.
// ! 可用 `按位或 (|)` 进行组合, `按位与 (&)` 进行检测, 互不干扰.
// ! 不可将其修改为 0x0101/0x0102/0x0103/0x0104/... 的形式,
// ! 以避免标志重叠造成组合与检测逻辑失效, 如 `flags & AS_GLOBAL` 可能出现误判.
// !
const val AS_GLOBAL = 0x0100
const val AS_IGNORED = 0x0200
const val AS_LITERAL_TO_STRING = 0x0400
const val AS_FUNCTIONAL_TO_STRING = 0x0800
val globalContext: Context
get() = GlobalAppContext.get()
fun refineAttributes(attributes: Int) = attributes and (READONLY or DONTENUM or PERMANENT or UNINITIALIZED_CONST)
private fun isInternalName(value: String) = value.startsWith("__") && value.endsWith("__")
private fun ScriptableObject.defineWith(name: String, getter: Supplier<Any?>, setter: Consumer<Any?>?, attributes: Int) {
when (isInternalName(name)) {
true -> this.defineProperty(name, getter, setter, DONTENUM or attributes)
else -> this.defineProperty(name, getter, setter, attributes)
}
}
private fun ScriptableObject.defineWith(name: String, value: Any?, attributes: Int) {
when (isInternalName(name)) {
true -> this.defineProperty(name, value, DONTENUM or attributes)
else -> this.defineProperty(name, value, attributes)
}
}
}
}

View File

@@ -1,8 +1,11 @@
package org.autojs.autojs.runtime.api.augment
import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.FlexibleArray.Companion.component2
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.rhino.ProxyObject
import org.autojs.autojs.rhino.ProxyObject.Companion.AUGMENTED_OBJECT_KEY
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
@@ -70,8 +73,9 @@ open class AugmentableProxy(private val scriptRuntime: ScriptRuntime) : Augmenta
return NOT_FOUND
}
open fun getCore(augmented: ScriptableObject, key: String): Any? {
return when (val value = augmented.prop(key)) {
open fun getCore(augmented: ScriptableObject, key: String): Any? = when (key) {
AUGMENTED_OBJECT_KEY -> augmented
else -> when (val value = augmented.prop(key)) {
is BaseFunction -> when {
// @Hint by SuperMonster003 on Nov 6, 2024.
// ! Indicated that `key` is not defined in `augmented`

View File

@@ -41,6 +41,7 @@ import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.Scriptable.NOT_FOUND
import org.mozilla.javascript.ScriptableObject.DONTENUM
import java.util.function.Supplier
import kotlin.math.abs
import kotlin.math.roundToInt
@@ -83,8 +84,10 @@ object Colors : Augmentable(), SimpleGetterProxy {
colorMap
}
private val allForNativeObject by lazy { all.toNativeObject() }
override val selfAssignmentFunctions = listOf(
"toString",
"toString" to AS_FUNCTIONAL_TO_STRING,
::toInt.name,
::toHex.name,
::toFullHex.name,
@@ -150,8 +153,8 @@ object Colors : Augmentable(), SimpleGetterProxy {
table::class.java.simpleName.lowercase() to table
}
override val selfAssignmentGetters = listOf<Pair<String, Supplier<Any?>>>(
"all" to Supplier { all.toNativeObject() },
override val selfAssignmentGetters = listOf(
"all" to Supplier { allForNativeObject } to DONTENUM,
)
@JvmStatic

View File

@@ -20,12 +20,15 @@ import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeJavaMethod
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.ScriptableObject.DONTENUM
import org.mozilla.javascript.ScriptableObject.PERMANENT
import org.mozilla.javascript.ScriptableObject.READONLY
import java.lang.reflect.Modifier
class Events(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override val selfAssignmentFunctions = listOf(
::__asEmitter__.name,
::__asEmitter__.name to (READONLY or DONTENUM or PERMANENT),
)
companion object : FlexibleArray() {

View File

@@ -58,7 +58,7 @@ class Global(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
)
override val selfAssignmentFunctions = listOf(
"toString",
"toString" to AS_LITERAL_TO_STRING,
::TODO.name,
::isUiThread.name,
::isJavaObject.name,

View File

@@ -65,7 +65,7 @@ import java.net.URI
class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override val selfAssignmentProperties = listOf(
"__okhttp__" to scriptRuntime.http.okhttp to DONTENUM
"__okhttp__" to scriptRuntime.http.okhttp to (READONLY or DONTENUM or PERMANENT)
)
override val selfAssignmentFunctions = listOf(

View File

@@ -31,7 +31,7 @@ import org.opencv.core.Rect as OpencvRect
class Ocr(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable {
override val selfAssignmentFunctions = listOf(
"toString",
"toString" to AS_LITERAL_TO_STRING,
::tap.name,
::recognizeText.name,
::detect.name,

View File

@@ -123,10 +123,10 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
::keepScreenOn.name,
)
override val selfAssignmentGetters = listOf<Pair<String, Supplier<Any?>>>(
override val selfAssignmentGetters = listOf(
"R" to Supplier { scriptRuntime.topLevelScope.prop("R").jsUnwrapped() },
"__widgets__" to Supplier { scriptRuntime.ui.widgets },
"root" to Supplier {
"root" to Supplier<Any?> {
val activity = getActivity(scriptRuntime)
(activity as? ScriptExecuteActivity)?.findViewById(android.R.id.content)
},

View File

@@ -10,6 +10,9 @@ import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.FlexibleArray.Companion.component2
import org.autojs.autojs.extension.NumberExtensions.jsString
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.rhino.ProxyObject
import org.autojs.autojs.rhino.ProxyObject.Companion.AUGMENTED_CUSTOM_TO_STRING_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.AUGMENTED_OBJECT_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_GETTER_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_SETTER_KEY
import org.autojs.autojs.runtime.api.StringReadable
@@ -17,8 +20,8 @@ import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.runtime.api.augment.global.Species.isErrorRhino
import org.autojs.autojs.runtime.api.augment.global.Species.isJavaObjectRhino
import org.autojs.autojs.runtime.api.augment.global.Species.isObjectRhino
import org.autojs.autojs.runtime.api.augment.global.Species.isStringRhino
import org.autojs.autojs.runtime.api.augment.util.Util.isReferenceRhino
import org.autojs.autojs.runtime.exception.ShouldNeverHappenException
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils
@@ -35,10 +38,12 @@ import org.autojs.autojs.util.RhinoUtils.js_object_keys
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context
import org.mozilla.javascript.MemberBox
import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeDate
import org.mozilla.javascript.NativeError
import org.mozilla.javascript.NativeJavaClass
import org.mozilla.javascript.NativeJavaMethod
import org.mozilla.javascript.NativeJavaPackage
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.Scriptable
@@ -75,7 +80,6 @@ object Inspect : Augmentable(), Invokable {
* SGR (Select Graphic Rendition) parameters
* @see <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters">"ANSI escape code" on Wikipedia (en)</a>
*/
@Suppress("SpellCheckingInspection")
private val srg = object {
val fg = object {
val BLACK = 30
@@ -306,21 +310,58 @@ object Inspect : Augmentable(), Invokable {
if (value is NativeJavaClass) return value.toString()
if (value.javaClass.isArray) return javaArrayToString(value)
if (value !is ScriptableObject) return Context.toString(value)
if (value is ProxyObject) return formatValue(ctx, value[AUGMENTED_OBJECT_KEY], recurseTimes)
// @Hint by SuperMonster003 on Apr 16, 2024.
// ! Check if the object has a custom overwritten toString() method.
// ! zh-CN: 检查对象是否有自定义的 toString() 覆写方法.
if (isObjectRhino(value)) {
var tmp: Scriptable = value
val objectPrototype by lazy { ScriptableObject.getObjectPrototype(value) }
do {
if (js_object_hasOwnProperty(tmp, "toString")) {
if ((tmp.prop("toString") as? BaseFunction)?.arity == 0) {
return callToStringFunction(value)
}
if (isReferenceRhino(value)) {
var cur: Scriptable = value
val objProtoForJs: Scriptable? = ScriptableObject.getObjectPrototype(cur)
val objProtoForAugmentable: Scriptable = RhinoUtils.objectPrototype
val arrProtoForAugmentable: Scriptable = RhinoUtils.arrayPrototype
val funcProtoForAugmentable: Scriptable = RhinoUtils.functionPrototype
var owner: Scriptable? = null
while (true) {
if (js_object_hasOwnProperty(cur, "toString")) {
owner = cur
break
}
tmp = tmp.prototype ?: break
} while (tmp != objectPrototype)
cur = cur.prototype ?: break
}
if (js_object_hasOwnProperty(cur, AUGMENTED_CUSTOM_TO_STRING_KEY)) {
// Augmentable's custom toString method with special functionality (like Colors.toString)
// is not involved in custom determination.
// zh-CN: Augmentable 自定义的具有特殊功能的 toString 方法 (如 Colors.toString), 不参与自定义判定.
} else if (owner != null) {
val fn = owner["toString"]
val isCustom = run {
if (isJavaObjectToString(fn)) {
// Standard Java Object#toString or equivalent implementation, skip custom check.
// zh-CN: 标准 Java Object#toString 或等价实现, 视为未自定义, 跳过自定义判定.
return@run false
}
if (fn === objProtoForJs?.get("toString")) {
// Standard JavaScript Object.prototype.toString or equivalent implementation, skip custom check.
// zh-CN: 标准 JavaScript Object.prototype.toString 或等价实现, 视为未自定义, 跳过自定义判定.
return@run false
}
val augmentableToStringList = listOf(
objProtoForAugmentable["toString"],
arrProtoForAugmentable["toString"],
funcProtoForAugmentable["toString"],
)
if (fn in augmentableToStringList) {
// Terminal toString in Augmentable prototype chain, skip custom check.
// zh-CN: Augmentable 原型链终端的 toString, 不参与自定义判定.
return@run false
}
return@run fn is BaseFunction && fn.arity == 0
}
if (isCustom) {
return callToStringFunction(value)
}
}
}
// Look up the keys of the object.
@@ -328,7 +369,6 @@ object Inspect : Augmentable(), Invokable {
val visibleKeys = newNativeObject().also { o ->
keys.forEach { o.put(Context.toString(it), o, true) }
}
if (ctx.showHidden) {
keys = js_object_getOwnPropertyNames(value)
}
@@ -419,6 +459,18 @@ object Inspect : Augmentable(), Invokable {
return reduceToSingleString(output, base, braces)
}
private fun isJavaObjectToString(fn: Any?): Boolean {
if (fn !is NativeJavaMethod) return false
val methods: Array<out MemberBox> = fn.methods
return methods.any { mb ->
val m = mb.method()
m.name == "toString" &&
m.parameterCount == 0 &&
m.returnType == String::class.java &&
m.declaringClass == Any::class.java
}
}
private fun toJavaObjectString(value: Any) = "[JavaObject: ${value.javaClass.name}@${Integer.toHexString(value.hashCode())}]"
private fun toJavaObjectString(className: Any?, value: Any?) = "[JavaObject: $className@${Integer.toHexString(value.hashCode())}]"

View File

@@ -20,10 +20,10 @@ import org.mozilla.javascript.Scriptable
class MorseCodeNativeObject(val parser: MorseCodeParser) : NativeObject(), StringReadable {
private val mFunctionNames = arrayOf(
"toString",
::getPattern.name,
::getCode.name,
::vibrate.name,
"toString",
)
init {

View File

@@ -62,6 +62,7 @@ import org.mozilla.javascript.ScriptRuntime as RhinoScriptRuntime
object Util : Augmentable() {
override val selfAssignmentFunctions = listOf(
::__assignFunctions__.name to (READONLY or DONTENUM or PERMANENT),
::isArray.name,
::isBoolean.name,
::isNull.name,
@@ -84,7 +85,6 @@ object Util : Augmentable() {
::isEmptyObject.name,
::unwrapJavaObject.name,
::extend.name,
::__assignFunctions__.name,
::format.name,
::deprecate.name,
::debuglog.name,

View File

@@ -5,6 +5,7 @@ import org.autojs.autojs.annotation.RhinoStandardFunctionInterface
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.extension.ArrayExtensions.toNativeArray
import org.autojs.autojs.extension.FlexibleArray
import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.NumberExtensions.jsString
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.runtime.api.augment.Augmentable
@@ -18,6 +19,7 @@ import org.mozilla.javascript.NativeDate
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.ScriptRuntime.wrapNumber
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject.DONTENUM
import org.mozilla.javascript.ScriptableObject.PERMANENT
import org.mozilla.javascript.ScriptableObject.READONLY
import java.util.*
@@ -26,7 +28,7 @@ import java.util.*
object VersionCodes : Augmentable() {
override val selfAssignmentFunctions = listOf(
"toString",
"toString" to AS_LITERAL_TO_STRING,
::search.name,
::searchAll.name,
::summary.name,
@@ -84,14 +86,14 @@ object VersionCodes : Augmentable() {
val releaseTimestamp = releaseTimestampLong.jsString
fun toNativeObject() = newNativeObject().also {
it.put("versionCode", it, versionCode)
it.put("apiLevel", it, apiLevel.toInt())
it.put("releaseName", it, releaseName)
it.put("platformVersion", it, platformVersion)
it.put("internalCodename", it, internalCodename)
it.put("releaseDate", it, releaseDate)
it.put("releaseTimestamp", it, releaseTimestampLong)
it.defineFunctionProperties(arrayOf("valueOf"), javaClass, READONLY and PERMANENT)
it.defineProperty("versionCode", versionCode, READONLY or PERMANENT)
it.defineProperty("apiLevel", apiLevel.toInt(), READONLY or PERMANENT)
it.defineProperty("releaseName", releaseName, READONLY or PERMANENT)
it.defineProperty("platformVersion", platformVersion, READONLY or PERMANENT)
it.defineProperty("internalCodename", internalCodename, READONLY or PERMANENT)
it.defineProperty("releaseDate", releaseDate, READONLY or PERMANENT)
it.defineProperty("releaseTimestamp", releaseTimestampLong, READONLY or PERMANENT)
it.defineFunctionProperties(arrayOf("valueOf"), javaClass, READONLY or DONTENUM or PERMANENT)
}
private fun parseTimestamp(s: String): Long {
@@ -130,7 +132,9 @@ object VersionCodes : Augmentable() {
fun valueOf(cx: Context, thisObj: Scriptable, args: Array<Any?>, funObj: Function): Any? {
return thisObj.prop("apiLevel")
}
}
}
internal object Searcher {

View File

@@ -3,6 +3,8 @@ package org.autojs.autojs.runtime.api.augment.util
import android.os.Build
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.mozilla.javascript.ScriptableObject.PERMANENT
import org.mozilla.javascript.ScriptableObject.READONLY
object VersionCodesInfo {
@@ -55,7 +57,7 @@ object VersionCodesInfo {
for ((versionCode, infoList) in raw) {
val (releaseName, internalCodename, platformVersion, apiLevel, releaseDate) = infoList
val info = VersionCodes.Info(versionCode, releaseName, internalCodename, platformVersion, apiLevel, releaseDate)
obj.put(versionCode, obj, info.toNativeObject())
obj.defineProperty(versionCode, { info.toNativeObject() }, null, READONLY or PERMANENT)
list += info
}
}

View File

@@ -217,7 +217,7 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp
}
private void applyComponentInformation() {
if (WrappedShizuku.isOperational() && WrappedShizuku.service != null) {
if (WrappedShizuku.INSTANCE.isOperational() && WrappedShizuku.service != null) {
try {
mRunningPackage = WrappedShizuku.service.currentPackage();
mRunningActivity = WrappedShizuku.service.currentActivity();

View File

@@ -127,7 +127,7 @@ object RhinoUtils {
fun callFunction(scriptRuntime: ScriptRuntime?, obj: Scriptable, name: String, paramsToFunction: Array<Any?>): Any? {
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")
if (property !is BaseFunction) throw IllegalArgumentException("Property $name on $obj must be a BaseFunction instead of ${property.jsBrief()}")
return callFunction(scriptRuntime, property, obj, obj, paramsToFunction)
}