[net8.0] Merge main into net8.0.
This commit is contained in:
Коммит
58b5d14d8c
|
@ -70,12 +70,12 @@ while test "x$1" != x; do
|
|||
echo "Disabled all platforms"
|
||||
shift
|
||||
;;
|
||||
--disable-mac)
|
||||
--disable-mac | --disable-macos)
|
||||
echo "INCLUDE_MAC=" >> $CONFIGURED_FILE
|
||||
echo "Mac Build disabled"
|
||||
shift
|
||||
;;
|
||||
--enable-mac)
|
||||
--enable-mac | --enable-macos)
|
||||
echo "INCLUDE_MAC=1" >> $CONFIGURED_FILE
|
||||
echo "Mac Build enabled"
|
||||
shift
|
||||
|
|
|
@ -231,16 +231,14 @@ namespace Foundation {
|
|||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
static T AllocateNSObject<T> (IntPtr handle) where T : NSObject
|
||||
{
|
||||
var obj = (T) RuntimeHelpers.GetUninitializedObject (typeof (T));
|
||||
obj.handle = handle;
|
||||
obj.flags = Flags.NativeRef;
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, Flags flags)
|
||||
{
|
||||
#if NET
|
||||
if (Runtime.IsManagedStaticRegistrar) {
|
||||
throw new System.Diagnostics.UnreachableException ();
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function is called from native code before any constructors have executed.
|
||||
var type = (Type) Runtime.GetGCHandleTarget (type_gchandle);
|
||||
try {
|
||||
|
|
|
@ -1820,7 +1820,7 @@ namespace HealthKit {
|
|||
bool HasUndeterminedDuration { get; }
|
||||
}
|
||||
|
||||
delegate void HKSampleQueryResultsHandler (HKSampleQuery query, HKSample [] results, NSError error);
|
||||
delegate void HKSampleQueryResultsHandler (HKSampleQuery query, [NullAllowed] HKSample [] results, [NullAllowed] NSError error);
|
||||
|
||||
[Mac (13, 0)]
|
||||
[MacCatalyst (13, 1)]
|
||||
|
|
|
@ -919,6 +919,9 @@ namespace Xamarin.Tests {
|
|||
|
||||
public static IEnumerable<ApplePlatform> GetIncludedPlatforms (bool dotnet)
|
||||
{
|
||||
if (dotnet && !include_dotnet)
|
||||
yield break;
|
||||
|
||||
if (include_ios)
|
||||
yield return ApplePlatform.iOS;
|
||||
if (include_tvos)
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace Xamarin.Linker {
|
|||
|
||||
Dictionary<AssemblyDefinition, Dictionary<string, (TypeDefinition, TypeReference)>> type_map = new ();
|
||||
Dictionary<string, (MethodDefinition, MethodReference)> method_map = new ();
|
||||
Dictionary<string, (FieldDefinition, FieldReference)> field_map = new ();
|
||||
|
||||
public AppBundleRewriter (LinkerConfiguration configuration)
|
||||
{
|
||||
|
@ -176,6 +177,23 @@ namespace Xamarin.Linker {
|
|||
return $"{method?.ReturnType?.FullName ?? "(null)"} {method?.DeclaringType?.FullName ?? "(null)"}::{method?.Name ?? "(null)"} ({string.Join (", ", method?.Parameters?.Select (v => v?.ParameterType?.FullName + " " + v?.Name) ?? Array.Empty<string> ())})";
|
||||
}
|
||||
|
||||
public FieldReference GetFieldReference (AssemblyDefinition assembly, TypeReference tr, string name, string key, out FieldDefinition field)
|
||||
{
|
||||
if (!field_map.TryGetValue (key, out var tuple)) {
|
||||
var td = tr.Resolve ();
|
||||
var fd = td.Fields.SingleOrDefault (v => v.Name == name);
|
||||
if (fd is null)
|
||||
throw new InvalidOperationException ($"Unable to find the field '{tr.FullName}::{name}' (for key '{key}') in {assembly.Name.Name}. Fields in type:\n\t{string.Join ("\n\t", td.Fields.Select (f => f.Name).OrderBy (v => v))}");
|
||||
|
||||
tuple.Item1 = fd;
|
||||
tuple.Item2 = CurrentAssembly.MainModule.ImportReference (fd);
|
||||
field_map.Add (key, tuple);
|
||||
}
|
||||
|
||||
field = tuple.Item1;
|
||||
return tuple.Item2;
|
||||
}
|
||||
|
||||
/* Types */
|
||||
|
||||
public TypeReference System_Boolean {
|
||||
|
@ -267,6 +285,12 @@ namespace Xamarin.Linker {
|
|||
}
|
||||
}
|
||||
|
||||
public TypeReference System_ValueType {
|
||||
get {
|
||||
return GetTypeReference (CorlibAssembly, "System.ValueType", out var _);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeReference System_Collections_Generic_Dictionary2 {
|
||||
get {
|
||||
return GetTypeReference (CorlibAssembly, "System.Collections.Generic.Dictionary`2", out var _);
|
||||
|
@ -321,6 +345,26 @@ namespace Xamarin.Linker {
|
|||
}
|
||||
}
|
||||
|
||||
public FieldReference Foundation_NSObject_HandleField {
|
||||
get {
|
||||
return GetFieldReference (PlatformAssembly, Foundation_NSObject, "handle", "Foundation.NSObject::handle", out var _);
|
||||
}
|
||||
}
|
||||
|
||||
#if NET
|
||||
public MethodReference Foundation_NSObject_FlagsSetterMethod {
|
||||
get {
|
||||
return GetMethodReference (PlatformAssembly, Foundation_NSObject, "set_flags", "Foundation.NSObject::set_flags", predicate: null, out var _);
|
||||
}
|
||||
}
|
||||
#else
|
||||
public FieldReference Foundation_NSObject_FlagsField {
|
||||
get {
|
||||
return GetFieldReference (PlatformAssembly, Foundation_NSObject, "flags", "Foundation.NSObject::flags", out var _);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public TypeReference ObjCRuntime_BindAs {
|
||||
get {
|
||||
return GetTypeReference (PlatformAssembly, "ObjCRuntime.BindAs", out var _);
|
||||
|
@ -449,17 +493,6 @@ namespace Xamarin.Linker {
|
|||
}
|
||||
}
|
||||
|
||||
public MethodReference NSObject_AllocateNSObject {
|
||||
get {
|
||||
return GetMethodReference (PlatformAssembly,
|
||||
Foundation_NSObject, "AllocateNSObject",
|
||||
nameof (NSObject_AllocateNSObject),
|
||||
isStatic: true,
|
||||
genericParameterCount: 1,
|
||||
System_IntPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodReference BindAs_ConvertNSArrayToManagedArray {
|
||||
get {
|
||||
return GetMethodReference (PlatformAssembly, ObjCRuntime_BindAs, "ConvertNSArrayToManagedArray", (v) =>
|
||||
|
|
|
@ -30,6 +30,14 @@ namespace Xamarin.Linker {
|
|||
return rv;
|
||||
}
|
||||
|
||||
public static FieldDefinition AddField (this TypeDefinition self, string name, FieldAttributes attributes, TypeReference type)
|
||||
{
|
||||
var rv = new FieldDefinition (name, attributes, type);
|
||||
rv.DeclaringType = self;
|
||||
self.Fields.Add (rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static MethodBody CreateBody (this MethodDefinition self, out ILProcessor il)
|
||||
{
|
||||
var body = new MethodBody (self);
|
||||
|
|
|
@ -401,6 +401,7 @@ namespace Xamarin.Linker {
|
|||
var placeholderType = abr.System_IntPtr;
|
||||
ParameterDefinition? callSuperParameter = null;
|
||||
VariableDefinition? returnVariable = null;
|
||||
MethodReference? ctor = null;
|
||||
var leaveTryInstructions = new List<Instruction> ();
|
||||
var isVoid = method.ReturnType.Is ("System", "Void");
|
||||
|
||||
|
@ -425,6 +426,7 @@ namespace Xamarin.Linker {
|
|||
// and later on remove everything after this instruction. Maybe at a later point I'll figure out a way to make the code emission conditional without
|
||||
// littering the logic with conditional statements.
|
||||
Instruction? skipEverythingAfter = null;
|
||||
|
||||
if (isInstanceCategory) {
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
EmitConversion (method, il, method.Parameters [0].ParameterType, true, 0, out var nativeType, postProcessing);
|
||||
|
@ -459,12 +461,32 @@ namespace Xamarin.Linker {
|
|||
// We're throwing an exception, so there's no need for any more code.
|
||||
skipEverythingAfter = il.Body.Instructions.Last ();
|
||||
} else {
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
// Whenever there's an NSObject constructor that we call from a registrar callback, we need to create
|
||||
// a separate constructor that will first set the `handle` and `flags` values of the NSObject before
|
||||
// calling the original constructor. Here's an example of the code we generate:
|
||||
//
|
||||
// // The original constructor:
|
||||
// public .ctor (T0 p0, T1 p1, ...) { /* ... */ }
|
||||
//
|
||||
// // The generated constructor with pre-initialization:
|
||||
// public .ctor (T0 p0, T1 p1, ..., IntPtr nativeHandle, IManagedRegistrar dummy) {
|
||||
// this.handle = (NativeHandle)nativeHandle;
|
||||
// this.flags = 2; // Flags.NativeRef == 2
|
||||
// this..ctor (p0, p1, ...);
|
||||
// }
|
||||
//
|
||||
// - This code can't be expressed in C# and it can only be expressed directly in IL.
|
||||
// - The reason we need to do this is because the base NSObject parameterless constructor
|
||||
// would allocate a new Objective-C object if `handle` is a zero pointer.
|
||||
// - The `IManagedRegistrar` dummy parameter is used only to make sure that the signature
|
||||
// is unique and there aren't any conflicts. The IManagedRegistrar type is internal and
|
||||
// we only make it public through a custom linker step.
|
||||
|
||||
ctor = CloneConstructorWithNativeHandle (method);
|
||||
method.DeclaringType.Methods.Add (ctor.Resolve ());
|
||||
|
||||
il.Emit (OpCodes.Nop);
|
||||
postLeaveBranch.Operand = il.Body.Instructions.Last ();
|
||||
var git = new GenericInstanceMethod (abr.NSObject_AllocateNSObject);
|
||||
git.GenericArguments.Add (method.DeclaringType);
|
||||
il.Emit (OpCodes.Call, git);
|
||||
il.Emit (OpCodes.Dup); // this is for the call to ObjCRuntime.NativeObjectExtensions::GetHandle after the call to the constructor
|
||||
}
|
||||
} else if (isGeneric) {
|
||||
// this is a proxy method and we can simply use `this` without any conversion
|
||||
|
@ -509,7 +531,13 @@ namespace Xamarin.Linker {
|
|||
|
||||
callback.AddParameter ("exception_gchandle", new PointerType (abr.System_IntPtr));
|
||||
|
||||
if (isGeneric && !method.IsConstructor) {
|
||||
if (ctor is not null) {
|
||||
// in addition to the params of the original ctor we pass also the native handle and a null
|
||||
// value for the dummy (de-duplication) parameter
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
il.Emit (OpCodes.Ldnull);
|
||||
il.Emit (OpCodes.Newobj, ctor);
|
||||
} else if (isGeneric && !method.IsConstructor) {
|
||||
var targetMethod = method.DeclaringType.CreateMethodReferenceOnGenericType (method, method.DeclaringType.GenericParameters.ToArray ());
|
||||
il.Emit (OpCodes.Call, targetMethod);
|
||||
} else if (method.IsStatic) {
|
||||
|
@ -1270,5 +1298,58 @@ namespace Xamarin.Linker {
|
|||
il.Append (endTarget);
|
||||
}
|
||||
}
|
||||
|
||||
MethodDefinition CloneConstructorWithNativeHandle (MethodDefinition ctor)
|
||||
{
|
||||
var clonedCtor = new MethodDefinition (ctor.Name, ctor.Attributes, ctor.ReturnType);
|
||||
clonedCtor.IsPublic = false;
|
||||
|
||||
// clone the original parameters firsts
|
||||
foreach (var parameter in ctor.Parameters) {
|
||||
clonedCtor.AddParameter (parameter.Name, parameter.ParameterType);
|
||||
}
|
||||
|
||||
// add a native handle param + a dummy parameter that we know for a fact won't be used anywhere
|
||||
// to make the signature of the new constructor unique
|
||||
var handleParameter = clonedCtor.AddParameter ("nativeHandle", abr.System_IntPtr);
|
||||
var dummyParameter = clonedCtor.AddParameter ("dummy", abr.ObjCRuntime_IManagedRegistrar);
|
||||
|
||||
var body = clonedCtor.CreateBody (out var il);
|
||||
|
||||
// ensure visible
|
||||
abr.Foundation_NSObject_HandleField.Resolve ().IsFamily = true;
|
||||
#if NET
|
||||
abr.Foundation_NSObject_FlagsSetterMethod.Resolve ().IsFamily = true;
|
||||
#else
|
||||
abr.Foundation_NSObject_FlagsField.Resolve ().IsFamily = true;
|
||||
#endif
|
||||
|
||||
// store the handle and flags first
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
il.Emit (OpCodes.Ldarg, handleParameter);
|
||||
#if NET
|
||||
il.Emit (OpCodes.Call, abr.NativeObject_op_Implicit_NativeHandle);
|
||||
#endif
|
||||
il.Emit (OpCodes.Stfld, abr.CurrentAssembly.MainModule.ImportReference (abr.Foundation_NSObject_HandleField));
|
||||
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
il.Emit (OpCodes.Ldc_I4_2); // Flags.NativeRef == 2
|
||||
#if NET
|
||||
il.Emit (OpCodes.Call, abr.Foundation_NSObject_FlagsSetterMethod);
|
||||
#else
|
||||
il.Emit (OpCodes.Stfld, abr.Foundation_NSObject_FlagsField);
|
||||
#endif
|
||||
|
||||
// call the original constructor with all of the original parameters
|
||||
il.Emit (OpCodes.Ldarg_0);
|
||||
foreach (var parameter in clonedCtor.Parameters.SkipLast (2)) {
|
||||
il.Emit (OpCodes.Ldarg, parameter);
|
||||
}
|
||||
|
||||
il.Emit (OpCodes.Call, ctor);
|
||||
il.Emit (OpCodes.Ret);
|
||||
|
||||
return clonedCtor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче