From 96f6bc180532ca599270bd6b9e072a25fc23ab98 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 22 May 2020 16:00:25 +0900 Subject: [PATCH] =?UTF-8?q?NativeString.get=E3=81=A7java.lang.String?= =?UTF-8?q?=E3=81=AE=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89=E3=82=82=E6=A4=9C?= =?UTF-8?q?=E7=B4=A2=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anatawa12/fixRtm/asm/RhinoTransformer.kt | 38 ++++++++++++++++ .../fixRtm/scripting/PrimitiveJavaHelper.kt | 44 +++++++++++++++++++ .../fixRtm/scripting/inRhinoPackage.kt | 25 +++++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/main/java/com/anatawa12/fixRtm/scripting/PrimitiveJavaHelper.kt create mode 100644 src/main/java/com/anatawa12/fixRtm/scripting/inRhinoPackage.kt diff --git a/src/main/java/com/anatawa12/fixRtm/asm/RhinoTransformer.kt b/src/main/java/com/anatawa12/fixRtm/asm/RhinoTransformer.kt index 8a053f70..5d7984ed 100644 --- a/src/main/java/com/anatawa12/fixRtm/asm/RhinoTransformer.kt +++ b/src/main/java/com/anatawa12/fixRtm/asm/RhinoTransformer.kt @@ -1,5 +1,6 @@ package com.anatawa12.fixRtm.asm +import com.anatawa12.fixRtm.scripting.PrimitiveJavaHelper import com.anatawa12.fixRtm.scripting.RhinoHooks import net.minecraft.launchwrapper.IClassTransformer import org.objectweb.asm.* @@ -17,6 +18,11 @@ class RhinoTransformer : IClassTransformer { val writer = ClassWriter(0) reader.accept(NativeJavaObjectVisitor(writer), 0) return writer.toByteArray() + } else if (name == PrimitiveJavaHelper.NativeString_name) { + val reader = ClassReader(basicClass!!) + val writer = ClassWriter(0) + reader.accept(NativeStringVisitor(writer), 0) + return writer.toByteArray() } return basicClass } @@ -108,6 +114,34 @@ class RhinoTransformer : IClassTransformer { } } + class NativeStringVisitor(visitor: ClassVisitor): ClassVisitor(ASM5, visitor) { + override fun visitEnd() { + visitMethod(ACC_PUBLIC, PrimitiveJavaHelper.get_name, PrimitiveJavaHelper.get_desc, + null, null).apply { + visitCode() + visitVarInsn(ALOAD, 0) // this + visitVarInsn(ALOAD, 1) // name + visitVarInsn(ALOAD, 2) // start + visitMethodInsn(INVOKESPECIAL, IdScriptableObject_internal, PrimitiveJavaHelper.get_name, PrimitiveJavaHelper.get_desc, false) + visitInsn(DUP) + visitFieldInsn(GETSTATIC, Scriptable_internal, Scriptable_NOT_FOUND_name, Scriptable_NOT_FOUND_desc) + val ifEq = Label() + visitJumpInsn(IF_ACMPEQ, ifEq) + visitInsn(ARETURN) + visitLabel(ifEq) + visitFrame(F_SAME1, 0, null, 1, arrayOf("java/lang/Object")) + visitInsn(POP) + visitVarInsn(ALOAD, 1) // name + visitVarInsn(ALOAD, 2) // start + visitMethodInsn(INVOKESTATIC, PrimitiveJavaHelper.internalClassName, PrimitiveJavaHelper.NativeString_get_hook_name, PrimitiveJavaHelper.NativeString_get_hook_desc, false) + visitInsn(ARETURN) + visitMaxs(3, 3) + visitEnd() + } + super.visitEnd() + } + } + class InsertCodeAtFirstVisitor(visitor: MethodVisitor, private val function: MethodVisitor.() -> Unit) : MethodVisitor(ASM5, visitor) { private var visited = false @@ -127,5 +161,9 @@ class RhinoTransformer : IClassTransformer { const val NativeJavaObject_name = "org.mozilla.javascript.NativeJavaObject" const val NativeJavaObject_internal = "org/mozilla/javascript/NativeJavaObject" const val CoerceTypeImplFailed_internal = "com/anatawa12/fixRtm/scripting/CoerceTypeImplFailed" + const val IdScriptableObject_internal = "org/mozilla/javascript/IdScriptableObject" + const val Scriptable_internal = "org/mozilla/javascript/Scriptable" + const val Scriptable_NOT_FOUND_name = "NOT_FOUND" + const val Scriptable_NOT_FOUND_desc = "L${"java/lang/Object"};" } } diff --git a/src/main/java/com/anatawa12/fixRtm/scripting/PrimitiveJavaHelper.kt b/src/main/java/com/anatawa12/fixRtm/scripting/PrimitiveJavaHelper.kt new file mode 100644 index 00000000..8cdbe67f --- /dev/null +++ b/src/main/java/com/anatawa12/fixRtm/scripting/PrimitiveJavaHelper.kt @@ -0,0 +1,44 @@ +package com.anatawa12.fixRtm.scripting + +import org.mozilla.javascript.* + +@Suppress("FunctionName") +object PrimitiveJavaHelper { + const val internalClassName = "com/anatawa12/fixRtm/scripting/PrimitiveJavaHelper" + + const val NativeString_name = "org.mozilla.javascript.NativeString" + const val NativeString_internal = "org/mozilla/javascript/NativeString" + const val get_name = "get" + const val get_desc = "(Lj${"ava/lang/String"};L${"org/mozilla/javascript/Scriptable"};)L${"java/lang/Object"};" + const val NativeString_get_hook_name = "NativeString_get" + const val NativeString_get_hook_desc = "(L${"java/lang/String"};L${"org/mozilla/javascript/Scriptable"};)L${"java/lang/Object"};" + const val NativeString_string_name = "string" + const val NativeString_string_desc = "L${"java/lang/CharSequence"};" + + @JvmStatic + fun NativeString_get(name: String?, start: Scriptable?): Any? { + if (name in StringMethod_names) return Scriptable.NOT_FOUND + return wrapFunctionForString(stringObject.get(name, start)) + } + + private val stringObject = NativeJavaObject(null, "", null) + + private fun wrapFunctionForString(scriptable: Any?): Any? { + if (scriptable is NativeJavaMethod) + return FixRTMWrappedFunction(scriptable, ::getStringInstance) + else + return scriptable + } + + @JvmStatic + fun getStringInstance(scriptable: Scriptable) = FixRTMRhinoAccessor.getStringOfNativeString(scriptable) + + val StringMethod_names = setOf( + "charAt", "charCodeAt", "codePointAt", "concat", "includes", "endsWith", "indexOf", "lastIndexOf", + "localeCompare", "match", "normalize", "padEnd", "padStart", "quote", "repeat", "replace", "search", + "slice", "split", "startsWith", "substr", "substring", "toLocaleLowerCase", "toLocaleUpperCase", + "toLowerCase", "toSource", "toString", "toUpperCase", "trim", "trimStart", "trimLeft", "trimEnd", + "trimRight", "valueOf", "anchor", "big", "blink", "bold", "fixed", "fontcolor", "fontsize", "italics", + "link", "small", "strike", "sub", "sup" + ) +} diff --git a/src/main/java/com/anatawa12/fixRtm/scripting/inRhinoPackage.kt b/src/main/java/com/anatawa12/fixRtm/scripting/inRhinoPackage.kt new file mode 100644 index 00000000..d51fbf4f --- /dev/null +++ b/src/main/java/com/anatawa12/fixRtm/scripting/inRhinoPackage.kt @@ -0,0 +1,25 @@ +@file:Suppress("PackageDirectoryMismatch") + +package org.mozilla.javascript + +class FixRTMWrappedFunction(private val javaFunction: NativeJavaMethod, private val getInstance: (Scriptable) -> Any?) : BaseFunction() { + override fun getFunctionName(): String = javaFunction.functionName + override fun decompile(indent: Int, flags: Int): String = javaFunction.decompile(indent, flags) + override fun toString(): String = javaFunction.toString() + + override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable?, args: Array?): Any { + return javaFunction.call(cx, scope, thisObj?.let { wrap(cx, scope, thisObj) }, args) + } + + private fun wrap(cx: Context, scope: Scriptable, thisObj: Scriptable?): Scriptable? { + if (thisObj == null) return null + val topLevel = ScriptableObject.getTopLevelScope(scope) + return cx.wrapFactory.wrapNewObject(cx, topLevel, getInstance(thisObj)) + } +} + +object FixRTMRhinoAccessor { + fun getStringOfNativeString(scriptable: Scriptable): String? + = (scriptable as? NativeString)?.toCharSequence()?.toString() + +}