[generator] Add missing `EnsureUIThread` for generated `init` and `initWithCoder` (#8250)

Fix https://github.com/xamarin/xamarin-macios/issues/8249
This commit is contained in:
Sebastien Pouliot 2020-03-31 17:20:44 -04:00 коммит произвёл GitHub
Родитель 862d200a18
Коммит ac01b522f0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 61 добавлений и 7 удалений

Просмотреть файл

@ -4184,20 +4184,25 @@ public partial class Generator : IMemberGatherer {
string CurrentMethod;
void GenerateThreadCheck ()
void GenerateThreadCheck (StreamWriter sw = null)
{
string s;
switch (CurrentPlatform) {
case PlatformName.iOS:
case PlatformName.WatchOS:
case PlatformName.TvOS:
print ("global::{0}.UIApplication.EnsureUIThread ();", ns.Get ("UIKit"));
s = $"global::{ns.Get ("UIKit")}.UIApplication.EnsureUIThread ();";
break;
case PlatformName.MacOSX:
print ("global::{0}.NSApplication.EnsureUIThread ();", ns.Get ("AppKit"));
s = $"global::{ns.Get ("AppKit")}.NSApplication.EnsureUIThread ();";
break;
default:
throw new BindingException (1047, CurrentPlatform);
}
if (sw == null)
print (s);
else
sw.WriteLine (s);
}
// Stret.NeedStret is shared between generator and X.I dll so in order to wrap the exception
@ -6451,6 +6456,10 @@ public partial class Generator : IMemberGatherer {
sw.WriteLine ("\tthrow new PlatformNotSupportedException (\"This API is not supported on this version of iOS\");");
sw.WriteLine ("\t\t#else");
}
if (type_needs_thread_checks) {
sw.Write ("\t\t\t");
GenerateThreadCheck (sw);
}
var indentation = 3;
WriteIsDirectBindingCondition (sw, ref indentation, is_direct_binding, is_direct_binding_value,
() => string.Format ("InitializeHandle (global::{1}.IntPtr_objc_msgSend (this.Handle, global::{2}.{0}), \"init\");", initSelector, ns.Messaging, ns.CoreObjCRuntime),
@ -6478,7 +6487,10 @@ public partial class Generator : IMemberGatherer {
if (nscoding) {
if (debug)
sw.WriteLine ("\t\t\tConsole.WriteLine (\"{0}.ctor (NSCoder)\");", TypeName);
sw.WriteLine ();
if (type_needs_thread_checks) {
sw.Write ("\t\t\t");
GenerateThreadCheck (sw);
}
var indentation = 3;
WriteIsDirectBindingCondition (sw, ref indentation, is_direct_binding, is_direct_binding_value,
() => string.Format ("InitializeHandle (global::{1}.IntPtr_objc_msgSend_IntPtr (this.Handle, {0}, coder.Handle), \"initWithCoder:\");", initWithCoderSelector, ns.Messaging),

Просмотреть файл

@ -63,8 +63,11 @@ namespace Cecil.Tests {
yield return new TestCaseData (Path.Combine (Configuration.MonoTouchRootDirectory, "lib", "32bits", "Xamarin.iOS.dll"));
yield return new TestCaseData (Path.Combine (Configuration.MonoTouchRootDirectory, "lib", "64bits", "Xamarin.iOS.dll"));
yield return new TestCaseData (Configuration.XamarinWatchOSDll);
yield return new TestCaseData (Configuration.XamarinTVOSDll);
// XamarinWatchOSDll is stripped of its IL
yield return new TestCaseData (Path.Combine (Configuration.MonoTouchRootDirectory, "lib", "32bits", "Xamarin.WatchOS.dll"));
// XamarinTVOSDll is stripped of it's IL
yield return new TestCaseData (Path.Combine (Configuration.MonoTouchRootDirectory, "lib", "64bits", "Xamarin.TVOS.dll"));
yield return new TestCaseData (Configuration.XamarinMacMobileDll);
yield return new TestCaseData (Configuration.XamarinMacFullDll);
}

Просмотреть файл

@ -48,5 +48,43 @@ namespace Cecil.Tests {
}
}
}
[TestCaseSource (typeof (Helper), "PlatformAssemblies")]
// ref: https://github.com/xamarin/xamarin-macios/issues/8249
public void EnsureUIThreadOnInit (string assemblyPath)
{
var assembly = Helper.GetAssembly (assemblyPath);
if (assembly == null) {
Assert.Ignore ("{assemblyPath} could not be found (might be disabled in build)");
return; // just to help nullability
}
// `CNContactsUserDefaults` is `[ThreadSafe (false)]` and part of iOS and macOS
var t = assembly.MainModule.GetType ("Contacts.CNContactsUserDefaults");
if (t == null) {
// tvOS does not have the type so let's find an alternative
t = assembly.MainModule.GetType ("PhotosUI.PHLivePhotoView");
}
if (t == null) {
Assert.Fail ($"No type found for {assembly}");
return; // just to help nullability
}
foreach (var c in t.Methods) {
if (!c.IsConstructor || c.IsStatic || c.HasParameters)
continue;
// .ctor(IntPtr)
var found = false;
foreach (var ins in c.Body.Instructions) {
if (ins.OpCode.Code != Code.Call)
continue;
found |= (ins.Operand as MethodReference)?.Name == "EnsureUIThread";
}
if (!found)
Assert.Fail ("EnsureUIThread missing");
else
return; // single case, no point in iterating anymore
}
}
}
}

Просмотреть файл

@ -12,7 +12,7 @@ namespace Introspection
[TestFixture]
public class MacApiTypoTest : ApiTypoTest
{
NSSpellChecker checker = new NSSpellChecker ();
NSSpellChecker checker;
[SetUp]
public void SetUp ()
@ -20,6 +20,7 @@ namespace Introspection
var sdk = new Version (Constants.SdkVersion);
if (!PlatformHelper.CheckSystemVersion (sdk.Major, sdk.Minor))
Assert.Ignore ("Typos only verified using the latest SDK");
checker = new NSSpellChecker ();
}
public override string GetTypo (string txt)