diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index 32ab43f84f..f8b5337574 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -19,6 +19,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0001
+ T:Avalonia.Utilities.StringTokenizer
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0001
T:Avalonia.Controls.Primitives.IScrollable
@@ -49,6 +55,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0001
+ T:Avalonia.Utilities.StringTokenizer
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0001
T:Avalonia.Controls.Primitives.IScrollable
@@ -73,6 +85,24 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Input.KeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Input.TextInput.TextInputMethodClient.ShowInputPanel
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Media.DrawingImage.get_Viewbox
@@ -181,6 +211,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
CP0002
F:Avalonia.Controls.TextBlock.LetterSpacingProperty
@@ -223,6 +259,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+ CP0002
+ M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.Control)
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
CP0002
M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.ITemplate{Avalonia.Controls.Control})
@@ -259,6 +301,18 @@
baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+ CP0002
+ M:Avalonia.Controls.Primitives.TextSearch.GetText(Avalonia.Controls.Control)
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+
+ CP0002
+ M:Avalonia.Controls.Primitives.TextSearch.SetText(Avalonia.Controls.Control,System.String)
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
CP0002
M:Avalonia.Platform.Screen.#ctor(System.Double,Avalonia.PixelRect,Avalonia.PixelRect,System.Boolean)
@@ -343,6 +397,24 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Input.KeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Input.TextInput.TextInputMethodClient.ShowInputPanel
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Media.DrawingImage.get_Viewbox
@@ -451,6 +523,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
CP0002
F:Avalonia.Controls.TextBlock.LetterSpacingProperty
@@ -493,6 +571,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+ CP0002
+ M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.Control)
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
CP0002
M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.ITemplate{Avalonia.Controls.Control})
@@ -529,6 +613,18 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+ CP0002
+ M:Avalonia.Controls.Primitives.TextSearch.GetText(Avalonia.Controls.Control)
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+
+ CP0002
+ M:Avalonia.Controls.Primitives.TextSearch.SetText(Avalonia.Controls.Control,System.String)
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
CP0002
M:Avalonia.Platform.Screen.#ctor(System.Double,Avalonia.PixelRect,Avalonia.PixelRect,System.Boolean)
@@ -619,6 +715,12 @@
baseline/netstandard2.0/Avalonia.Base.dll
target/netstandard2.0/Avalonia.Base.dll
+
+ CP0006
+ M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers,System.Nullable{Avalonia.Input.KeyDeviceType})
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Platform.IDrawingContextImpl.PopTextOptions
@@ -727,6 +829,12 @@
baseline/Avalonia/lib/net6.0/Avalonia.OpenGL.dll
current/Avalonia/lib/net6.0/Avalonia.OpenGL.dll
+
+ CP0006
+ M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers,System.Nullable{Avalonia.Input.KeyDeviceType})
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Input.Platform.IClipboard.SetDataAsync(Avalonia.Input.IAsyncDataTransfer)
diff --git a/src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs b/src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
index 6ab0031f31..e82bb5d216 100644
--- a/src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
+++ b/src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
@@ -24,9 +24,11 @@ namespace Avalonia.Input
/// The current element.
/// The direction to move.
/// Any key modifiers active at the time of focus.
- void Move(
+ /// The device type used to move the focus.
+ bool Move(
IInputElement element,
NavigationDirection direction,
- KeyModifiers keyModifiers = KeyModifiers.None);
+ KeyModifiers keyModifiers = KeyModifiers.None,
+ KeyDeviceType? deviceType = null);
}
}
diff --git a/src/Avalonia.Base/Input/KeyboardNavigationHandler.cs b/src/Avalonia.Base/Input/KeyboardNavigationHandler.cs
index 3444a88aba..e5e7eb0699 100644
--- a/src/Avalonia.Base/Input/KeyboardNavigationHandler.cs
+++ b/src/Avalonia.Base/Input/KeyboardNavigationHandler.cs
@@ -98,22 +98,12 @@ namespace Avalonia.Input
return result;
}
- ///
- /// Moves the focus in the specified direction.
- ///
- /// The current element.
- /// The direction to move.
- /// Any key modifiers active at the time of focus.
- public void Move(
+ ///
+ public bool Move(
IInputElement? element,
NavigationDirection direction,
- KeyModifiers keyModifiers = KeyModifiers.None)
- {
- MovePrivate(element, direction, keyModifiers, null);
- }
-
- // TODO12: remove MovePrivate, and make Move return boolean. Or even remove whole KeyboardNavigationHandler.
- private bool MovePrivate(IInputElement? element, NavigationDirection direction, KeyModifiers keyModifiers, KeyDeviceType? deviceType)
+ KeyModifiers keyModifiers = KeyModifiers.None,
+ KeyDeviceType? deviceType = null)
{
var next = GetNextPrivate(element, _owner, direction, deviceType);
@@ -140,7 +130,7 @@ namespace Avalonia.Input
var current = FocusManager.GetFocusManager(e.Source as IInputElement)?.GetFocusedElement();
var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ?
NavigationDirection.Next : NavigationDirection.Previous;
- e.Handled = MovePrivate(current, direction, e.KeyModifiers, e.KeyDeviceType);
+ e.Handled = Move(current, direction, e.KeyModifiers, e.KeyDeviceType);
}
else if (e.Key is Key.Left or Key.Right or Key.Up or Key.Down)
{
@@ -153,7 +143,7 @@ namespace Avalonia.Input
Key.Down => NavigationDirection.Down,
_ => throw new ArgumentOutOfRangeException()
};
- e.Handled = MovePrivate(current, direction, e.KeyModifiers, e.KeyDeviceType);
+ e.Handled = Move(current, direction, e.KeyModifiers, e.KeyDeviceType);
}
}
diff --git a/src/Avalonia.Base/Input/TextInput/TextInputMethodClient.cs b/src/Avalonia.Base/Input/TextInput/TextInputMethodClient.cs
index 7f9870315b..36e14cd3fd 100644
--- a/src/Avalonia.Base/Input/TextInput/TextInputMethodClient.cs
+++ b/src/Avalonia.Base/Input/TextInput/TextInputMethodClient.cs
@@ -82,13 +82,6 @@ namespace Avalonia.Input.TextInput
{
SetPreeditText(preeditText);
}
-
- //TODO12: remove
- [Obsolete]
- public virtual void ShowInputPanel()
- {
- RaiseInputPaneActivationRequested();
- }
protected virtual void RaiseTextViewVisualChanged()
{
diff --git a/src/Avalonia.Base/Utilities/StringTokenizer.cs b/src/Avalonia.Base/Utilities/StringTokenizer.cs
deleted file mode 100644
index e83ef8c479..0000000000
--- a/src/Avalonia.Base/Utilities/StringTokenizer.cs
+++ /dev/null
@@ -1,245 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using static System.Char;
-
-namespace Avalonia.Utilities
-{
- // TODO12: Remove this struct in 12.0 (breaking change)
-
- [Obsolete("This type has been superseded by SpanStringTokenizer.")]
-#if !BUILDTASK
- public
-#endif
- record struct StringTokenizer : IDisposable
- {
- private const char DefaultSeparatorChar = ',';
-
- private readonly string _s;
- private readonly int _length;
- private readonly char _separator;
- private readonly string? _exceptionMessage;
- private readonly IFormatProvider _formatProvider;
- private int _index;
- private int _tokenIndex;
- private int _tokenLength;
-
- public StringTokenizer(string s, IFormatProvider formatProvider, string? exceptionMessage = null)
- : this(s, GetSeparatorFromFormatProvider(formatProvider), exceptionMessage)
- {
- _formatProvider = formatProvider;
- }
-
- public StringTokenizer(string s, char separator = DefaultSeparatorChar, string? exceptionMessage = null)
- {
- _s = s ?? throw new ArgumentNullException(nameof(s));
- _length = s?.Length ?? 0;
- _separator = separator;
- _exceptionMessage = exceptionMessage;
- _formatProvider = CultureInfo.InvariantCulture;
- _index = 0;
- _tokenIndex = -1;
- _tokenLength = 0;
-
- while (_index < _length && IsWhiteSpace(_s, _index))
- {
- _index++;
- }
- }
-
- public string? CurrentToken => _tokenIndex < 0 ? null : _s.Substring(_tokenIndex, _tokenLength);
-
- public ReadOnlySpan CurrentTokenSpan => _tokenIndex < 0 ? ReadOnlySpan.Empty : _s.AsSpan().Slice(_tokenIndex, _tokenLength);
-
- public void Dispose()
- {
- if (_index != _length)
- {
- throw GetFormatException();
- }
- }
-
- public bool TryReadInt32(out Int32 result, char? separator = null)
- {
- if (TryReadSpan(out var stringResult, separator) &&
- SpanHelpers.TryParseInt(stringResult, NumberStyles.Integer, _formatProvider, out result))
- {
- return true;
- }
- else
- {
- result = default;
- return false;
- }
- }
-
- public int ReadInt32(char? separator = null)
- {
- if (!TryReadInt32(out var result, separator))
- {
- throw GetFormatException();
- }
-
- return result;
- }
-
- public bool TryReadDouble(out double result, char? separator = null)
- {
- if (TryReadSpan(out var stringResult, separator) &&
- SpanHelpers.TryParseDouble(stringResult, NumberStyles.Float, _formatProvider, out result))
- {
- return true;
- }
- else
- {
- result = default;
- return false;
- }
- }
-
- public double ReadDouble(char? separator = null)
- {
- if (!TryReadDouble(out var result, separator))
- {
- throw GetFormatException();
- }
-
- return result;
- }
-
- public bool TryReadString([NotNull] out string result, char? separator = null)
- {
- var success = TryReadToken(separator ?? _separator);
- result = CurrentTokenSpan.ToString();
- return success;
- }
-
- public string ReadString(char? separator = null)
- {
- if (!TryReadString(out var result, separator))
- {
- throw GetFormatException();
- }
-
- return result;
- }
-
- public bool TryReadSpan(out ReadOnlySpan result, char? separator = null)
- {
- var success = TryReadToken(separator ?? _separator);
- result = CurrentTokenSpan;
- return success;
- }
-
- public ReadOnlySpan ReadSpan(char? separator = null)
- {
- if (!TryReadSpan(out var result, separator))
- {
- throw GetFormatException();
- }
-
- return result;
- }
-
- private bool TryReadToken(char separator)
- {
- _tokenIndex = -1;
-
- if (_index >= _length)
- {
- return false;
- }
-
- var c = _s[_index];
-
- var index = _index;
- var length = 0;
-
- while (_index < _length)
- {
- c = _s[_index];
-
- if (IsWhiteSpace(c) || c == separator)
- {
- break;
- }
-
- _index++;
- length++;
- }
-
- SkipToNextToken(separator);
-
- _tokenIndex = index;
- _tokenLength = length;
-
- if (_tokenLength < 1)
- {
- throw GetFormatException();
- }
-
- return true;
- }
-
- private void SkipToNextToken(char separator)
- {
- if (_index < _length)
- {
- var c = _s[_index];
-
- if (c != separator && !IsWhiteSpace(c))
- {
- throw GetFormatException();
- }
-
- var length = 0;
-
- while (_index < _length)
- {
- c = _s[_index];
-
- if (c == separator)
- {
- length++;
- _index++;
-
- if (length > 1)
- {
- throw GetFormatException();
- }
- }
- else
- {
- if (!IsWhiteSpace(c))
- {
- break;
- }
-
- _index++;
- }
- }
-
- if (length > 0 && _index >= _length)
- {
- throw GetFormatException();
- }
- }
- }
-
- private FormatException GetFormatException() =>
- _exceptionMessage != null ? new FormatException(_exceptionMessage) : new FormatException();
-
- private static char GetSeparatorFromFormatProvider(IFormatProvider provider)
- {
- var c = DefaultSeparatorChar;
-
- var formatInfo = NumberFormatInfo.GetInstance(provider);
- if (formatInfo.NumberDecimalSeparator.Length > 0 && c == formatInfo.NumberDecimalSeparator[0])
- {
- c = ';';
- }
-
- return c;
- }
- }
-}
diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
index 313e66b207..bc6380a012 100644
--- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
+++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
@@ -62,9 +62,6 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
-
- Markup/%(RecursiveDir)%(FileName)%(Extension)
-
Markup/%(RecursiveDir)%(FileName)%(Extension)
diff --git a/src/Avalonia.Controls/Design.cs b/src/Avalonia.Controls/Design.cs
index 9d6bb93ebb..1e7912d75f 100644
--- a/src/Avalonia.Controls/Design.cs
+++ b/src/Avalonia.Controls/Design.cs
@@ -127,22 +127,6 @@ namespace Avalonia.Controls
///
public static readonly AttachedProperty PreviewWithProperty = AvaloniaProperty
.RegisterAttached("PreviewWith", typeof (Design));
-
- ///
- /// Sets a preview template for the specified at design-time.
- ///
- ///
- /// This method allows you to specify a substitute control to be rendered in the previewer
- /// for a given object.
- ///
- /// The target object.
- /// The preview control.
- // TODO12: Remove this overload in Avalonia 12
- [Obsolete("Use SetPreviewWith(AvaloniaObject, ITemplate) overload instead. Use from XAML")]
- public static void SetPreviewWith(AvaloniaObject target, Control? control)
- {
- s_previewWith[target] = control is not null ? new FuncTemplate(() => control) : null;
- }
///
/// Sets a preview template for the specified at design-time.
diff --git a/src/Avalonia.Controls/Documents/Inline.cs b/src/Avalonia.Controls/Documents/Inline.cs
index 1ededcf81c..fe526e9204 100644
--- a/src/Avalonia.Controls/Documents/Inline.cs
+++ b/src/Avalonia.Controls/Documents/Inline.cs
@@ -10,11 +10,10 @@ namespace Avalonia.Controls.Documents
///
public abstract class Inline : TextElement
{
- // TODO12: change the field type to an AttachedProperty for consistency (breaking change)
///
/// AvaloniaProperty for property.
///
- public static readonly StyledProperty TextDecorationsProperty =
+ public static readonly AttachedProperty TextDecorationsProperty =
AvaloniaProperty.RegisterAttached(
nameof(TextDecorations),
inherits: true);
diff --git a/src/Avalonia.Controls/Primitives/TextSearch.cs b/src/Avalonia.Controls/Primitives/TextSearch.cs
index 5099567630..aa83266683 100644
--- a/src/Avalonia.Controls/Primitives/TextSearch.cs
+++ b/src/Avalonia.Controls/Primitives/TextSearch.cs
@@ -24,22 +24,20 @@ namespace Avalonia.Controls.Primitives
public static readonly AttachedProperty TextBindingProperty
= AvaloniaProperty.RegisterAttached("TextBinding", typeof(TextSearch));
- // TODO12: Control should be Interactive to match the property definition.
///
/// Sets the value of the attached property to a given .
///
/// The control.
/// The search text to set.
- public static void SetText(Control control, string? text)
+ public static void SetText(Interactive control, string? text)
=> control.SetValue(TextProperty, text);
- // TODO12: Control should be Interactive to match the property definition.
///
/// Gets the value of the attached property from a given .
///
/// The control.
/// The search text.
- public static string? GetText(Control control)
+ public static string? GetText(Interactive control)
=> control.GetValue(TextProperty);
///
diff --git a/src/Browser/Avalonia.Browser/Rendering/RenderWorker.cs b/src/Browser/Avalonia.Browser/Rendering/RenderWorker.cs
index f854e922f8..91495ea0ea 100644
--- a/src/Browser/Avalonia.Browser/Rendering/RenderWorker.cs
+++ b/src/Browser/Avalonia.Browser/Rendering/RenderWorker.cs
@@ -1,10 +1,7 @@
using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.JavaScript;
-using System.Threading;
using System.Threading.Tasks;
using Avalonia.Browser.Interop;
@@ -19,11 +16,14 @@ internal partial class RenderWorker
private static partial void InitializeRenderTargets();
internal static int WorkerThreadId;
+
+ // The worker task needs to be rooted otherwise the web worker will exit.
+ private static Task? s_workerTask;
public static Task InitializeAsync()
{
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- var workerTask = JSWebWorkerClone.RunAsync(async () =>
+ s_workerTask = JSWebWorkerRunAsync(null, async () =>
{
try
{
@@ -41,103 +41,18 @@ internal partial class RenderWorker
}
});
- workerTask.ContinueWith(_ =>
+ s_workerTask.ContinueWith(_ =>
{
- if (workerTask.IsFaulted)
- tcs.TrySetException(workerTask.Exception);
+ if (s_workerTask.IsFaulted)
+ tcs.TrySetException(s_workerTask.Exception);
});
return tcs.Task;
}
- public static class JSWebWorkerClone
- {
- private static readonly MethodInfo _setExtLoop;
- private static readonly MethodInfo _intallInterop;
-
- [DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Runtime.InteropServices.JavaScript.JSSynchronizationContext",
- "System.Runtime.InteropServices.JavaScript")]
- [DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Runtime.InteropServices.JavaScript.JSHostImplementation",
- "System.Runtime.InteropServices.JavaScript")]
- [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2036", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Private runtime API")]
- static JSWebWorkerClone()
- {
- var syncContext = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
- .Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSSynchronizationContext")!;
- var hostImpl = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
- .Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSHostImplementation")!;
-
- _setExtLoop = hostImpl.GetMethod("SetHasExternalEventLoop")!;
- _intallInterop = syncContext.GetMethod("InstallWebWorkerInterop")!;
- }
-
- public static Task RunAsync(Func run)
- {
- var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- var th = new Thread(_ =>
- {
- _intallInterop.Invoke(null, [false, CancellationToken.None]);
- try
- {
- run().ContinueWith(t =>
- {
- if (t.IsFaulted)
- tcs.TrySetException(t.Exception);
- else if (t.IsCanceled)
- tcs.TrySetCanceled();
- else
- tcs.TrySetResult();
- });
- }
- catch(Exception e)
- {
- tcs.TrySetException(e);
- }
- })
- {
- Name = "Manual JS worker"
- };
- _setExtLoop.Invoke(null, [th]);
-#pragma warning disable CA1416
- th.Start();
-#pragma warning restore CA1416
- return tcs.Task;
- }
-
- }
-
- // TODO: Use this class instead of JSWebWorkerClone once https://github.com/dotnet/runtime/issues/102010 is fixed
- // TODO12: It was fixed in .NET 10
- class JSWebWorkerWrapper
- {
- [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.JSWebWorker",
- "System.Runtime.InteropServices.JavaScript")]
- [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2036", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Private runtime API")]
- [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Private runtime API")]
- static JSWebWorkerWrapper()
- {
- var type = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
- .Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSWebWorker");
-#pragma warning disable IL2075
- var m = type!
-
- .GetMethods(BindingFlags.Static | BindingFlags.Public
- ).First(m => m.Name == "RunAsync"
- && m.ReturnType == typeof(Task)
- && m.GetParameters() is { } parameters
- && parameters.Length == 1
- && parameters[0].ParameterType == typeof(Func));
-
-#pragma warning restore IL2075
- RunAsync = (Func, Task>) Delegate.CreateDelegate(typeof(Func, Task>), m);
-
- }
-
- public static Func, Task> RunAsync { get; set; }
- }
+ // Even though this API is public in the .NET code, it's not part of ref assemblies and is not a stable API.
+ [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "RunAsync")]
+ private static extern Task JSWebWorkerRunAsync(
+ [UnsafeAccessorType("System.Runtime.InteropServices.JavaScript.JSWebWorker, System.Runtime.InteropServices.JavaScript")] object? instance,
+ Func body);
}
diff --git a/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs b/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs
deleted file mode 100644
index b7d09a40d7..0000000000
--- a/tests/Avalonia.Base.UnitTests/Utilities/StringTokenizerTests.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using Avalonia.Utilities;
-using Xunit;
-
-#pragma warning disable CS0618 // Type or member is obsolete
-
-namespace Avalonia.Base.UnitTests.Utilities
-{
- public class StringTokenizerTests
- {
- [Fact]
- public void ReadInt32_Reads_Values()
- {
- var target = new StringTokenizer("123,456");
-
- Assert.Equal(123, target.ReadInt32());
- Assert.Equal(456, target.ReadInt32());
- Assert.Throws(() => target.ReadInt32());
- }
-
- [Fact]
- public void ReadDouble_Reads_Values()
- {
- var target = new StringTokenizer("12.3,45.6");
-
- Assert.Equal(12.3, target.ReadDouble());
- Assert.Equal(45.6, target.ReadDouble());
- Assert.Throws(() => target.ReadDouble());
- }
-
- [Fact]
- public void TryReadInt32_Reads_Values()
- {
- var target = new StringTokenizer("123,456");
-
- Assert.True(target.TryReadInt32(out var value));
- Assert.Equal(123, value);
- Assert.True(target.TryReadInt32(out value));
- Assert.Equal(456, value);
- Assert.False(target.TryReadInt32(out value));
- }
-
- [Fact]
- public void TryReadInt32_Doesnt_Throw()
- {
- var target = new StringTokenizer("abc");
-
- Assert.False(target.TryReadInt32(out var value));
- }
-
- [Fact]
- public void TryReadDouble_Reads_Values()
- {
- var target = new StringTokenizer("12.3,45.6");
-
- Assert.True(target.TryReadDouble(out var value));
- Assert.Equal(12.3, value);
- Assert.True(target.TryReadDouble(out value));
- Assert.Equal(45.6, value);
- Assert.False(target.TryReadDouble(out value));
- }
-
- [Fact]
- public void TryReadDouble_Doesnt_Throw()
- {
- var target = new StringTokenizer("abc");
-
- Assert.False(target.TryReadDouble(out var value));
- }
-
- [Fact]
- public void ReadSpan_And_ReadString_Reads_Same()
- {
- var target1 = new StringTokenizer("abc,def");
- var target2 = new StringTokenizer("abc,def");
-
- Assert.Equal(target1.ReadString(), target2.ReadSpan().ToString());
- Assert.True(target1.ReadSpan().SequenceEqual(target2.ReadString()));
- }
- }
-}