mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-08-31 02:45:13 +00:00
419 lines
12 KiB
Haxe
419 lines
12 KiB
Haxe
package funkin.util;
|
|
|
|
import Type.ValueType;
|
|
|
|
/**
|
|
* Provides sanitized and blacklisted access to haxe's Reflection functions.
|
|
* Used for sandboxing in scripts.
|
|
*/
|
|
@:nullSafety
|
|
@SuppressWarnings("checkstyle:VarTypeHint")
|
|
class ReflectUtil
|
|
{
|
|
/**
|
|
* A list of field names which cannot be retrieved with `getAnonymousField()`
|
|
*/
|
|
static final FIELD_NAME_BLACKLIST:Array<String> = ['_interp'];
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function callMethod(obj:Any, name:String, args:Array<Any>):Any
|
|
{
|
|
throw "Function Reflect.callMethod is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* Compares two objects by value.
|
|
*
|
|
* @param valueA First value to compare
|
|
* @param valueB Second value to compare
|
|
* @return Int indicating relative order of values
|
|
*/
|
|
public static function compare(valueA:Any, valueB:Any):Int
|
|
{
|
|
return compareValues(valueA, valueB);
|
|
}
|
|
|
|
/**
|
|
* Compares two values and returns an integer indicating their relative order.
|
|
* Returns:
|
|
* - -1 if valueA < valueB
|
|
* - 0 if valueA == valueB
|
|
* - 1 if valueA > valueB
|
|
*
|
|
* @param valueA First value to compare
|
|
* @param valueB Second value to compare
|
|
* @return An integer indicating relative order of values
|
|
*/
|
|
public static function compareValues(valueA:Any, valueB:Any):Int
|
|
{
|
|
return Reflect.compare(valueA, valueB);
|
|
}
|
|
|
|
/**
|
|
* Compare the two Function objects to determine whether they are the same.
|
|
* @param functionA A method closure to compare.
|
|
* @param functionB A method closure to compare.
|
|
* @return Whether functionA and functionB are equal.
|
|
*/
|
|
public static function compareMethods(functionA:Any, functionB:Any):Bool
|
|
{
|
|
return Reflect.compareMethods(functionA, functionB);
|
|
}
|
|
|
|
/**
|
|
* Copies the given object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to copy.
|
|
* @return An independent clone of that object.
|
|
*/
|
|
public static function copy(obj:Any):Null<Any>
|
|
{
|
|
return copyAnonymousFieldsOf(obj);
|
|
}
|
|
|
|
/**
|
|
* Copies the anonymous structure to a new object.
|
|
* @param obj The object to copy.
|
|
* @return An independent clone of the structure.
|
|
*/
|
|
public static function copyAnonymousFieldsOf(obj:Any):Null<Any>
|
|
{
|
|
return Reflect.copy(obj);
|
|
}
|
|
|
|
/**
|
|
* Delete the field of a given name from an object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to delete the field from.
|
|
* @param name The name of the field to delete.
|
|
* @return Whether the operation was successful.
|
|
*/
|
|
public static function delete(obj:Any, name:String):Bool
|
|
{
|
|
return deleteAnonymousField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Delete the field of a given name from an anonymous structure.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to delete the field from.
|
|
* @param name The name of the field to delete.
|
|
* @return Whether the operation was successful.
|
|
*/
|
|
public static function deleteAnonymousField(obj:Any, name:String):Bool
|
|
{
|
|
return Reflect.deleteField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Retrive the value of a given field (by name) from an object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to delete the field from.
|
|
* @param name The name of the field to delete.
|
|
* @return Whether the operation was successful.
|
|
*/
|
|
public static function field(obj:Any, name:String):Any
|
|
{
|
|
return getAnonymousField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Retrive the value of a given field (by name) from an object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to delete the field from.
|
|
* @param name The name of the field to delete.
|
|
* @return Whether the operation was successful.
|
|
*/
|
|
public static function getField(obj:Any, name:String):Any
|
|
{
|
|
return getAnonymousField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Retrieve the value of the field of the given name from an anonymous structure.
|
|
* @param obj The object to query.
|
|
* @param name The name of the field to retrieve.
|
|
* @return The resulting field value.
|
|
* @throws error If the field is blacklisted.
|
|
*/
|
|
public static function getAnonymousField(obj:Any, name:String):Any
|
|
{
|
|
if (FIELD_NAME_BLACKLIST.contains(name))
|
|
{
|
|
throw 'Attempted to retrieve blacklisted field "${name}"';
|
|
};
|
|
|
|
return Reflect.field(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Get a list of fields available on the given object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to query.
|
|
* @return A list of fields on that object.
|
|
*/
|
|
public static function fields(obj:Any):Array<String>
|
|
{
|
|
return getAnonymousFieldsOf(obj);
|
|
}
|
|
|
|
/**
|
|
* Get a list of fields available on the given object.
|
|
* Only guaranteed to work on anonymous structures.
|
|
* @param obj The object to query.
|
|
* @return A list of fields on that object.
|
|
*/
|
|
public static function getFieldsOf(obj:Any):Array<String>
|
|
{
|
|
return getAnonymousFieldsOf(obj);
|
|
}
|
|
|
|
/**
|
|
* Get a list of fields available on the given anonymous structure.
|
|
* @param obj The object to query.
|
|
* @return A list of fields on that object.
|
|
*/
|
|
public static function getAnonymousFieldsOf(obj:Any):Array<String>
|
|
{
|
|
return Reflect.fields(obj);
|
|
}
|
|
|
|
/**
|
|
* Get the value of the given property on a given object.
|
|
* Unlike `getField()`, this will check if the field is a property with a getter function,
|
|
* and use that if appropriate.
|
|
* @param obj The object to query.
|
|
* @param name The name of the field to query.
|
|
* @return The value of the field.
|
|
* @throws error If the field is blacklisted.
|
|
*/
|
|
public static function getProperty(obj:Any, name:String):Any
|
|
{
|
|
if (FIELD_NAME_BLACKLIST.contains(name))
|
|
{
|
|
throw 'Attempted to retrieve blacklisted field "${name}"';
|
|
};
|
|
|
|
return Reflect.getProperty(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the given object has the given field.
|
|
* Only guaranteed to work for anonymous structures.
|
|
* @param obj The object to query.
|
|
* @param name The field name to query.
|
|
* @return Whether the field exists.
|
|
*/
|
|
public static function hasField(obj:Any, name:String):Bool
|
|
{
|
|
return hasAnonymousField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the given anonymous structure has the given field.
|
|
* @param obj The structure to query.
|
|
* @param name The field name to query.
|
|
* @return Whether the field exists.
|
|
*/
|
|
public static function hasAnonymousField(obj:Any, name:String):Bool
|
|
{
|
|
if (FIELD_NAME_BLACKLIST.contains(name))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return Reflect.hasField(obj, name);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the given input is an enum value.
|
|
* @param value The input to evaluate.
|
|
* @return Whether `value` is an enum value.
|
|
*/
|
|
public static function isEnumValue(value:Any):Bool
|
|
{
|
|
return Reflect.isEnumValue(value);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the given input is a callable function.
|
|
* @param value The input to evaluate.
|
|
* @return Whether `value` is a function.
|
|
*/
|
|
public static function isFunction(value:Any):Bool
|
|
{
|
|
return Reflect.isFunction(value);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the given input is an object.
|
|
* @param value The input to evaluate.
|
|
* @return Whether `value` is an object.
|
|
*/
|
|
public static function isObject(value:Any):Bool
|
|
{
|
|
return Reflect.isObject(value);
|
|
}
|
|
|
|
/**
|
|
* Set the value of a specific field on an object.
|
|
* Only guaranteed to work for anonymous structures.
|
|
* @param obj The object to modify.
|
|
* @param name The field to modify.
|
|
* @param value The new value to apply.
|
|
*/
|
|
public static function setField(obj:Any, name:String, value:Any):Void
|
|
{
|
|
return setAnonymousField(obj, name, value);
|
|
}
|
|
|
|
/**
|
|
* Set the value of a specific field on an anonymous structure.
|
|
* @param obj The object to modify.
|
|
* @param name The field to modify.
|
|
* @param value The new value to apply.
|
|
*/
|
|
public static function setAnonymousField(obj:Any, name:String, value:Any):Void
|
|
{
|
|
return Reflect.setField(obj, name, value);
|
|
}
|
|
|
|
/**
|
|
* Set the value of a specific field on an object.
|
|
* Accounts for property fields with getters and setters.
|
|
* @param obj The object to modify.
|
|
* @param name The field to modify.
|
|
* @param value The new value to apply.
|
|
*/
|
|
public static function setProperty(obj:Any, name:String, value:Any):Void
|
|
{
|
|
return Reflect.setProperty(obj, name, value);
|
|
}
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function createEmptyInstance(cls:Class<Any>):Any
|
|
{
|
|
throw "Function Type.createEmptyInstance is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function createInstance(cls:Class<Any>, args:Array<Any>):Any
|
|
{
|
|
throw "Function Type.createInstance is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function resolveClass(name:String):Class<Any>
|
|
{
|
|
throw "Function Type.resolveClass is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function resolveEnum(name:String):Enum<Any>
|
|
{
|
|
throw "Function Type.resolveEnum is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* This function is not allowed to be used by scripts.
|
|
* @throws error When called by a script.
|
|
*/
|
|
@SuppressWarnings("checkstyle:FieldDocComment")
|
|
public static function typeof(value:Any):ValueType
|
|
{
|
|
throw "Function Type.typeof is blacklisted.";
|
|
}
|
|
|
|
/**
|
|
* Get a list of the static class fields on the given class.
|
|
* @param cls The class object to query.
|
|
* @return A list of class field names.
|
|
*/
|
|
public static function getClassFields(cls:Class<Any>):Array<String>
|
|
{
|
|
return Type.getClassFields(cls);
|
|
}
|
|
|
|
/**
|
|
* Get a list of the static class fields on the class of the given object.
|
|
* @param obj The object whose class should be queried.
|
|
* @return A list of class field names.
|
|
*/
|
|
public static function getClassFieldsOf(obj:Any):Array<String>
|
|
{
|
|
if (obj == null) return [];
|
|
@:nullSafety(Off)
|
|
var cls = Type.getClass(obj);
|
|
if (cls == null) return [];
|
|
return Type.getClassFields(cls);
|
|
}
|
|
|
|
/**
|
|
* Get a list of all the fields on instances of the given class.
|
|
* @param cls The class object to query.
|
|
* @return A list of object field names.
|
|
*/
|
|
public static function getInstanceFields(cls:Class<Any>):Array<String>
|
|
{
|
|
return Type.getInstanceFields(cls);
|
|
}
|
|
|
|
/**
|
|
* Get a list of all the fields on instances of the class of the given object.
|
|
* @param obj The object whose class should be query.
|
|
* @return A list of object field names.
|
|
*/
|
|
public static function getInstanceFieldsOf(obj:Any):Array<String>
|
|
{
|
|
if (obj == null) return [];
|
|
@:nullSafety(Off)
|
|
var cls = Type.getClass(obj);
|
|
if (cls == null) return [];
|
|
return Type.getInstanceFields(cls);
|
|
}
|
|
|
|
/**
|
|
* Get the string name of the given class.
|
|
* @param cls The class to query.
|
|
* @return The name of the given class.
|
|
*/
|
|
public static function getClassName(cls:Class<Any>):String
|
|
{
|
|
return Type.getClassName(cls);
|
|
}
|
|
|
|
/**
|
|
* Get the string name of the class of the given object.
|
|
* @param obj The object to query.
|
|
* @return The name of the given class, or `Unknown` if the class couldn't be determined.
|
|
*/
|
|
public static function getClassNameOf(obj:Any):String
|
|
{
|
|
if (obj == null) return "Unknown";
|
|
@:nullSafety(Off)
|
|
var cls = Type.getClass(obj);
|
|
if (cls == null) return "Unknown";
|
|
return Type.getClassName(cls);
|
|
}
|
|
}
|