use interfaces from metadata instead of ClassNode in MixinPluginTransformer

This commit is contained in:
danyadev committed 2026-05-20 07:17:03 +03:00
1 parent c34d409a2d
commit 0a088c2f3a
4 files changed
+70 -11

No files matched your search

Vendored Regular → Executable
View File
File mode changed.
@@ -23,6 +23,7 @@
package com.falsepattern.lib.internal.asm.transformers;
import com.falsepattern.lib.internal.Tags;
import com.falsepattern.lib.turboasm.ClassHeaderMetadata;
import com.falsepattern.lib.turboasm.ClassNodeHandle;
import com.falsepattern.lib.turboasm.TurboClassTransformer;
import lombok.val;
@@ -75,17 +76,11 @@ public class MixinPluginTransformer implements TurboClassTransformer {
if (!classNode.isPresent())
return false;
if (classNode.isOriginal()) {
val meta = classNode.getOriginalMetadata();
if (meta != null && meta.interfacesCount == 0)
return false;
}
val cn = classNode.getNode();
if (cn == null)
ClassHeaderMetadata metadata = classNode.getOriginalMetadata();
if (metadata == null)
return false;
for (String i : cn.interfaces) {
for (String i : metadata.binaryInterfaceNames()) {
if (IMIXINPLUGIN_INTERNAL.equals(i) || IMIXINCONFIGPLUGIN_INTERNAL.equals(i)) {
return true;
}
@@ -30,6 +30,9 @@ import org.objectweb.asm.Opcodes;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Utilities for quickly processing class files without fully parsing them.
@@ -49,8 +52,11 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
public final int thisClassIndex;
public final int superClassIndex;
public final int interfacesCount;
public final int @NotNull [] interfaceIndices;
public final @NotNull String binaryThisName;
public final @Nullable String binarySuperName;
/** List is unmodifiable */
public final @NotNull List<@NotNull String> binaryInterfaceNames;
/**
* Attempts to parse a class header.
@@ -88,6 +94,9 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
this.thisClassIndex = u16(bytes, cpOff + Offsets.pastCpThisClassU16);
this.superClassIndex = u16(bytes, cpOff + Offsets.pastCpSuperClassU16);
this.interfacesCount = u16(bytes, cpOff + Offsets.pastCpInterfacesCountU16);
this.interfaceIndices = new int[this.interfacesCount];
List<String> interfaceNames = new ArrayList<>(this.interfacesCount);
// Parse this&super names
if (constantPoolEntryTypes[thisClassIndex - 1] != ConstantPoolEntryTypes.Class) {
throw new IllegalArgumentException("This class index is not a class ref");
@@ -110,6 +119,25 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
}
this.binarySuperName = modifiedUtf8(bytes, constantPoolEntryOffsets[superNameIndex - 1] + 1);
}
// Parse interface names
for (int i = 0; i < this.interfacesCount; i++) {
final int interfaceOffset = cpOff + Offsets.pastCpInterfacesList + i * 2;
final int interfaceIndex = u16(bytes, interfaceOffset);
if (constantPoolEntryTypes[interfaceIndex - 1] != ConstantPoolEntryTypes.Class) {
throw new IllegalArgumentException("Interface " + i + " index is not a class ref");
}
final int interfaceNameIndex = u16(bytes, constantPoolEntryOffsets[interfaceIndex - 1] + 1);
if (constantPoolEntryTypes[interfaceNameIndex - 1] != ConstantPoolEntryTypes.Utf8) {
throw new IllegalArgumentException("Interface " + i + " index does not point to a UTF8 entry");
}
final String binaryInterfaceName =
modifiedUtf8(bytes, constantPoolEntryOffsets[interfaceNameIndex - 1] + 1);
this.interfaceIndices[i] = interfaceIndex;
interfaceNames.add(binaryInterfaceName);
}
this.binaryInterfaceNames = Collections.unmodifiableList(interfaceNames);
}
/** Helpers to read big-endian values from class files. */
@@ -189,6 +217,8 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
public static final int pastCpSuperClassU16 = pastCpThisClassU16 + 2;
/** The value of the interfaces_count item gives the number of direct superinterfaces of this class or interface type */
public static final int pastCpInterfacesCountU16 = pastCpSuperClassU16 + 2;
public static final int pastCpInterfacesList = pastCpInterfacesCountU16 + 2;
}
public enum ConstantPoolEntryTypes {
@@ -354,4 +384,9 @@ public final class ClassHeaderMetadata implements FastClassAccessor {
public @Nullable String binarySuperName() {
return binarySuperName;
}
}
@Override
public @NotNull List<@NotNull String> binaryInterfaceNames() {
return binaryInterfaceNames;
}
}
@@ -28,6 +28,9 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** An accessor to metadata about a class that is quickly accessible without fully parsing one. */
public interface FastClassAccessor {
@@ -51,6 +54,9 @@ public interface FastClassAccessor {
/** Binary (slash-separated packages) name of the super-class, null for the Object class */
@Nullable
String binarySuperName();
/** Binary (slash-separated packages) names of the implemented interfaces, list is unmodifiable */
@NotNull
List<@NotNull String> binaryInterfaceNames();
static OfLoaded ofLoaded(Class<?> loadedClass) {
return new OfLoaded(loadedClass);
@@ -111,10 +117,18 @@ public interface FastClassAccessor {
public @Nullable String binarySuperName() {
return handle.superName;
}
@Override
public @NotNull List<@NotNull String> binaryInterfaceNames() {
return handle.interfaces == null
? Collections.emptyList()
: Collections.unmodifiableList(handle.interfaces);
}
}
final class OfLoaded implements FastClassAccessor {
public final Class<?> handle;
private @Nullable List<@NotNull String> interfacesCache = null;
private OfLoaded(Class<?> handle) {
this.handle = handle;
@@ -165,5 +179,20 @@ public interface FastClassAccessor {
final Class<?> superclass = handle.getSuperclass();
return superclass == null ? null : superclass.getName().replace('.', '/');
}
@Override
public @NotNull List<@NotNull String> binaryInterfaceNames() {
if (interfacesCache != null) {
return interfacesCache;
}
Class<?>[] interfaces = handle.getInterfaces();
List<String> binaryInterfaceNames = new ArrayList<>(interfaces.length);
for (Class<?> iface : interfaces) {
binaryInterfaceNames.add(iface.getName().replace('.', '/'));
}
interfacesCache = Collections.unmodifiableList(binaryInterfaceNames);
return interfacesCache;
}
}
}
}