From 7dbab4f10a891f884dfb4174eec206fc6bee6639 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Fri, 25 Nov 2022 14:35:12 -0500 Subject: [PATCH] perf(wasm): Enable trimming for external drag and drop --- build/cSpell.json | 1 + build/uno.winui.common.targets | 12 ++++++++- .../features/using-il-linker-webassembly.md | 24 ++++++++++++++++- .../Uno.UI.Tasks/Content/Uno.UI.Tasks.targets | 1 + .../Extensions/LinkerAttributes.cs | 2 +- src/Uno.UI/LinkerDefinition.Wasm.xml | 4 --- src/Uno.UI/LinkerSubstitution.Wasm.xml | 13 +++++++++ .../Xaml/DragDrop/DragDropExtension.wasm.cs | 27 ++++++++++++++++--- src/Uno.UI/Uno.UI.Wasm.csproj | 2 ++ .../DataTransfer/DragAndDropExtension.ts | 11 ++++++++ 10 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 src/Uno.UI/LinkerSubstitution.Wasm.xml diff --git a/build/cSpell.json b/build/cSpell.json index 1e16143cef0c..833f396bd1bb 100644 --- a/build/cSpell.json +++ b/build/cSpell.json @@ -111,6 +111,7 @@ "Udemy", "UNOB", "winui", + "illinker", ], "patterns": [ { diff --git a/build/uno.winui.common.targets b/build/uno.winui.common.targets index ef507d825e17..684f051af698 100644 --- a/build/uno.winui.common.targets +++ b/build/uno.winui.common.targets @@ -8,6 +8,17 @@ <_IsUnoPlatform>true + + + true + + + + + + - diff --git a/doc/articles/features/using-il-linker-webassembly.md b/doc/articles/features/using-il-linker-webassembly.md index f4e4b4cc47e7..2c34ba1c3b1b 100644 --- a/doc/articles/features/using-il-linker-webassembly.md +++ b/doc/articles/features/using-il-linker-webassembly.md @@ -1,4 +1,26 @@ -# Using the IL Linker for WebAssembly +--- +uid: articles.features.illinker +--- + +# Using the IL Linker + +### Support for features + +In order to improve the size of the application, some platforms are providing the ability to unconditionally disable features if the app is known not to use them. + +|Feature|MSBuild property|Description| +|-----|----|---| +|External Drag and Drop|`UnoDragDropExternalSupport`|Enables or disables drag and dropping content from **outside** the app using this property. Drag and Drop **inside** the app is always available when disabled.| + +For example, to disable external drag and drop support on WebAssembly, add the following to your csproj: + +```xml + + false + +``` + +## WebAssembly The [linker step](https://github.com/mono/linker/tree/master/docs) (also known as tree shaking, or IL Trimming) is responsible for the detection and removal of code that may not be used at runtime. This step is particularly important when targeting WebAssembly or native code in general, to reduce significantly the final package size. diff --git a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets index 556300afb421..599b19c0269f 100644 --- a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets +++ b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets @@ -103,6 +103,7 @@ AfterTargets="CoreCompile"> + <_SubstitutionFiles Include="@(UnoLinkerSubstitution)" /> <_SubstitutionFiles Include="$(IntermediateOutputPath)\Substitutions\*.Substitutions.xml" /> diff --git a/src/Uno.Foundation/Extensions/LinkerAttributes.cs b/src/Uno.Foundation/Extensions/LinkerAttributes.cs index 79b311799381..578e676ed252 100644 --- a/src/Uno.Foundation/Extensions/LinkerAttributes.cs +++ b/src/Uno.Foundation/Extensions/LinkerAttributes.cs @@ -3,7 +3,7 @@ #nullable enable -#if NETSTANDARD2_0 +#if !NET6_0_OR_GREATER || NETSTANDARD namespace System.Diagnostics.CodeAnalysis { /// diff --git a/src/Uno.UI/LinkerDefinition.Wasm.xml b/src/Uno.UI/LinkerDefinition.Wasm.xml index 33e9dcb6a26e..5fc2852d2b02 100644 --- a/src/Uno.UI/LinkerDefinition.Wasm.xml +++ b/src/Uno.UI/LinkerDefinition.Wasm.xml @@ -16,9 +16,6 @@ - - - @@ -92,5 +89,4 @@ - diff --git a/src/Uno.UI/LinkerSubstitution.Wasm.xml b/src/Uno.UI/LinkerSubstitution.Wasm.xml new file mode 100644 index 000000000000..a5bf227e5788 --- /dev/null +++ b/src/Uno.UI/LinkerSubstitution.Wasm.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/Uno.UI/UI/Xaml/DragDrop/DragDropExtension.wasm.cs b/src/Uno.UI/UI/Xaml/DragDrop/DragDropExtension.wasm.cs index 76f8026c8592..3a364f493fa2 100644 --- a/src/Uno.UI/UI/Xaml/DragDrop/DragDropExtension.wasm.cs +++ b/src/Uno.UI/UI/Xaml/DragDrop/DragDropExtension.wasm.cs @@ -28,6 +28,7 @@ using Uno.Storage.Internal; using Uno.UI; using Uno.UI.Xaml; +using System.Diagnostics.CodeAnalysis; // As IDragDropExtension is internal, the generated registration cannot be used. // [assembly: ApiExtension(typeof(Windows.ApplicationModel.DataTransfer.DragDrop.Core.IDragDropExtension), typeof(Windows.ApplicationModel.DataTransfer.DragDrop.Core.DragDropExtension))] @@ -42,6 +43,11 @@ internal class DragDropExtension : IDragDropExtension private static DragDropExtension? _current; + /// + /// Conditional support for external drag and drop. See the UnoDragDropExternalSupport msbuild property. + /// + public static bool IsExternalDragAndDropSupported { get; } = true; + public static DragDropExtension GetForCurrentView() { // Note: We use the GetForCurrentView naming pattern, but we don't support multi-threading yet @@ -49,10 +55,17 @@ public static DragDropExtension GetForCurrentView() if (_current is null && Interlocked.CompareExchange(ref _current, new DragDropExtension(), null) is null) { - // For now we enable the D&DExtension sync at creation and we don't support disable. - // This allow us to prevent a drop of a content on an app which actually don't support D&D - // (would drive the browser to open the dragged file and "dismiss" the app). - _current.Enable(); + if (IsExternalDragAndDropSupported) + { + // For now we enable the D&DExtension sync at creation and we don't support disable. + // This allow us to prevent a drop of a content on an app which actually don't support D&D + // (would drive the browser to open the dragged file and "dismiss" the app). + _current.Enable(); + } + else + { + EnableExternalWarning(); + } } return _current; @@ -70,6 +83,7 @@ private DragDropExtension() ?? throw new InvalidOperationException("No CoreDragDropManager available for current thread."); } + [DynamicDependency(nameof(OnNativeDropEvent))] private void Enable() { if (Interlocked.CompareExchange(ref _isInitialized, 1, 0) == 0) @@ -84,6 +98,11 @@ private void Enable() } } + private static void EnableExternalWarning() + { + WebAssemblyRuntime.InvokeJS("Windows.ApplicationModel.DataTransfer.DragDrop.Core.DragDropExtension.registerNoOp();"); + } + /// void IDragDropExtension.StartNativeDrag(CoreDragInfo info) { diff --git a/src/Uno.UI/Uno.UI.Wasm.csproj b/src/Uno.UI/Uno.UI.Wasm.csproj index 3d8e08089051..211dbc5dbcaf 100644 --- a/src/Uno.UI/Uno.UI.Wasm.csproj +++ b/src/Uno.UI/Uno.UI.Wasm.csproj @@ -59,6 +59,8 @@ + + $(AssemblyName).xml diff --git a/src/Uno.UI/ts/Windows/ApplicationModel/DataTransfer/DragAndDropExtension.ts b/src/Uno.UI/ts/Windows/ApplicationModel/DataTransfer/DragAndDropExtension.ts index 4761f4e07e49..9275dee536c8 100644 --- a/src/Uno.UI/ts/Windows/ApplicationModel/DataTransfer/DragAndDropExtension.ts +++ b/src/Uno.UI/ts/Windows/ApplicationModel/DataTransfer/DragAndDropExtension.ts @@ -61,6 +61,17 @@ document.removeEventListener("drop", this._dropHandler); } + public static registerNoOp() { + let notifyDisabled = (evt: DragEvent) => { + evt.dataTransfer.dropEffect = "none"; + console.debug("DragAndDrop from external sources is disabled. See the UnoDragDropExternalSupport msbuild property."); + + document.removeEventListener("dragenter", notifyDisabled); + }; + + document.addEventListener("dragenter", notifyDisabled); + } + private dispatchDropEvent(evt: DragEvent): any { if (evt.type == "dragleave" && evt.clientX > 0