Skip to content

Commit 8fbf7f2

Browse files
Eliminate framework use of 'IJSUnmarshalledRuntime' (#46693)
Co-authored-by: Steve Sanderson <[email protected]>
1 parent 46a3d2b commit 8fbf7f2

29 files changed

+413
-307
lines changed

src/Components/Shared/src/BrowserNavigationManagerInterop.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ internal static class BrowserNavigationManagerInterop
1010

1111
public const string EnableNavigationInterception = Prefix + "enableNavigationInterception";
1212

13-
public const string GetLocationHref = Prefix + "getUnmarshalledLocationHref";
13+
public const string GetLocationHref = Prefix + "getLocationHref";
1414

15-
public const string GetBaseUri = Prefix + "getUnmarshalledBaseURI";
15+
public const string GetBaseUri = Prefix + "getBaseURI";
1616

1717
public const string NavigateTo = Prefix + "navigateTo";
1818

src/Components/Web.JS/src/Boot.WebAssembly.ts

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import { DotNet } from '@microsoft/dotnet-js-interop';
66
import { Blazor } from './GlobalExports';
77
import * as Environment from './Environment';
8-
import { byteArrayBeingTransferred, Module, BINDING, monoPlatform } from './Platform/Mono/MonoPlatform';
8+
import { Module, BINDING, monoPlatform } from './Platform/Mono/MonoPlatform';
99
import { renderBatch, getRendererer, attachRootComponentToElement, attachRootComponentToLogicalElement } from './Rendering/Renderer';
1010
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
1111
import { shouldAutoStart } from './BootCommon';
1212
import { WebAssemblyResourceLoader } from './Platform/WebAssemblyResourceLoader';
1313
import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader';
1414
import { BootConfigResult } from './Platform/BootConfig';
15-
import { Pointer, System_Array, System_Boolean, System_Byte, System_Int, System_Object, System_String } from './Platform/Platform';
15+
import { Pointer } from './Platform/Platform';
1616
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
1717
import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher';
1818
import { discoverComponents, discoverPersistedState, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
@@ -52,9 +52,9 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
5252

5353
// Configure JS interop
5454
Blazor._internal.invokeJSFromDotNet = invokeJSFromDotNet;
55+
Blazor._internal.invokeJSJson = invokeJSJson;
5556
Blazor._internal.endInvokeDotNetFromJS = endInvokeDotNetFromJS;
5657
Blazor._internal.receiveByteArray = receiveByteArray;
57-
Blazor._internal.retrieveByteArray = retrieveByteArray;
5858

5959
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
6060
const platform = Environment.setPlatform(monoPlatform);
@@ -73,12 +73,6 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
7373
}
7474
};
7575

76-
// Configure navigation via JS Interop
77-
const getBaseUri = Blazor._internal.navigationManager.getBaseURI;
78-
const getLocationHref = Blazor._internal.navigationManager.getLocationHref;
79-
Blazor._internal.navigationManager.getUnmarshalledBaseURI = () => BINDING.js_string_to_mono_string(getBaseUri());
80-
Blazor._internal.navigationManager.getUnmarshalledLocationHref = () => BINDING.js_string_to_mono_string(getLocationHref());
81-
8276
Blazor._internal.navigationManager.listenForNavigationEvents(async (uri: string, state: string | undefined, intercepted: boolean): Promise<void> => {
8377
await DotNet.invokeMethodAsync(
8478
'Microsoft.AspNetCore.Components.WebAssembly',
@@ -114,13 +108,13 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
114108
Blazor._internal.registeredComponents = {
115109
getRegisteredComponentsCount: () => componentAttacher.getCount(),
116110
getId: (index) => componentAttacher.getId(index),
117-
getAssembly: (id) => BINDING.js_string_to_mono_string(componentAttacher.getAssembly(id)),
118-
getTypeName: (id) => BINDING.js_string_to_mono_string(componentAttacher.getTypeName(id)),
119-
getParameterDefinitions: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterDefinitions(id) || ''),
120-
getParameterValues: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterValues(id) || ''),
111+
getAssembly: (id) => componentAttacher.getAssembly(id),
112+
getTypeName: (id) => componentAttacher.getTypeName(id),
113+
getParameterDefinitions: (id) => componentAttacher.getParameterDefinitions(id) || '',
114+
getParameterValues: (id) => componentAttacher.getParameterValues(id) || '',
121115
};
122116

123-
Blazor._internal.getPersistedState = () => BINDING.js_string_to_mono_string(discoverPersistedState(document) || '');
117+
Blazor._internal.getPersistedState = () => discoverPersistedState(document) || '';
124118

125119
Blazor._internal.attachRootComponentToElement = (selector, componentId, rendererId: any) => {
126120
const element = componentAttacher.resolveRegisteredElement(selector);
@@ -191,26 +185,21 @@ function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any):
191185
}
192186
}
193187

194-
function endInvokeDotNetFromJS(callId: System_String, success: System_Boolean, resultJsonOrErrorMessage: System_String): void {
195-
const callIdString = BINDING.conv_string(callId)!;
196-
const successBool = (success as any as number) !== 0;
197-
const resultJsonOrErrorMessageString = BINDING.conv_string(resultJsonOrErrorMessage)!;
198-
DotNet.jsCallDispatcher.endInvokeDotNetFromJS(callIdString, successBool, resultJsonOrErrorMessageString);
188+
function invokeJSJson(identifier: string, targetInstanceId: number, resultType: number, argsJson: string, asyncHandle: number): string | null {
189+
if (asyncHandle !== 0) {
190+
DotNet.jsCallDispatcher.beginInvokeJSFromDotNet(asyncHandle, identifier, argsJson, resultType, targetInstanceId);
191+
return null;
192+
} else {
193+
return DotNet.jsCallDispatcher.invokeJSFromDotNet(identifier, argsJson, resultType, targetInstanceId);
194+
}
199195
}
200196

201-
function receiveByteArray(id: System_Int, data: System_Array<System_Byte>): void {
202-
const idLong = id as unknown as number;
203-
const dataByteArray = monoPlatform.toUint8Array(data);
204-
DotNet.jsCallDispatcher.receiveByteArray(idLong, dataByteArray);
197+
function endInvokeDotNetFromJS(callId: string, success: boolean, resultJsonOrErrorMessage: string): void {
198+
DotNet.jsCallDispatcher.endInvokeDotNetFromJS(callId, success, resultJsonOrErrorMessage);
205199
}
206200

207-
function retrieveByteArray(): System_Object {
208-
if (byteArrayBeingTransferred === null) {
209-
throw new Error('Byte array not available for transfer');
210-
}
211-
212-
const typedArray = BINDING.js_typed_array_to_array(byteArrayBeingTransferred);
213-
return typedArray;
201+
function receiveByteArray(id: number, data: Uint8Array): void {
202+
DotNet.jsCallDispatcher.receiveByteArray(id, data);
214203
}
215204

216205
function inAuthRedirectIframe(): boolean {

src/Components/Web.JS/src/GlobalExports.ts

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { NavigationLock } from './NavigationLock';
1212
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
1313
import { CircuitStartOptions } from './Platform/Circuits/CircuitStartOptions';
1414
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
15-
import { Platform, Pointer, System_String, System_Array, System_Object, System_Boolean, System_Byte, System_Int } from './Platform/Platform';
15+
import { Platform, Pointer } from './Platform/Platform';
1616
import { getNextChunk, receiveDotNetDataStream } from './StreamingInterop';
1717
import { RootComponentsFunctions } from './Rendering/JSRootComponents';
1818
import { attachWebRendererInterop } from './Rendering/WebRendererInteropMethods';
@@ -29,41 +29,49 @@ interface IBlazor {
2929
rootComponents: typeof RootComponentsFunctions;
3030

3131
_internal: {
32-
navigationManager: typeof navigationManagerInternalFunctions | any,
33-
domWrapper: typeof domFunctions,
34-
Virtualize: typeof Virtualize,
35-
PageTitle: typeof PageTitle,
32+
navigationManager: typeof navigationManagerInternalFunctions | any;
33+
domWrapper: typeof domFunctions;
34+
Virtualize: typeof Virtualize;
35+
PageTitle: typeof PageTitle;
3636
forceCloseConnection?: () => Promise<void>;
37-
InputFile?: typeof InputFile,
38-
NavigationLock: typeof NavigationLock,
37+
InputFile?: typeof InputFile;
38+
NavigationLock: typeof NavigationLock;
3939
invokeJSFromDotNet?: (callInfo: Pointer, arg0: any, arg1: any, arg2: any) => any;
40-
endInvokeDotNetFromJS?: (callId: System_String, success: System_Boolean, resultJsonOrErrorMessage: System_String) => void;
41-
receiveByteArray?: (id: System_Int, data: System_Array<System_Byte>) => void;
42-
retrieveByteArray?: () => System_Object;
43-
getPersistedState?: () => System_String;
40+
invokeJSJson?: (identifier: string, targetInstanceId: number, resultType: number, argsJson: string, asyncHandle: number) => string | null;
41+
endInvokeDotNetFromJS?: (callId: string, success: boolean, resultJsonOrErrorMessage: string) => void;
42+
receiveByteArray?: (id: number, data: Uint8Array) => void;
43+
getPersistedState?: () => string;
4444
attachRootComponentToElement?: (arg0: any, arg1: any, arg2: any, arg3: any) => void;
4545
registeredComponents?: {
46-
getRegisteredComponentsCount: () => number,
47-
getId: (index) => number,
48-
getAssembly: (id) => System_String,
49-
getTypeName: (id) => System_String,
50-
getParameterDefinitions: (id) => System_String,
51-
getParameterValues: (id) => any,
46+
getRegisteredComponentsCount: () => number;
47+
getId: (index) => number;
48+
getAssembly: (id) => string;
49+
getTypeName: (id) => string;
50+
getParameterDefinitions: (id) => string;
51+
getParameterValues: (id) => any;
5252
};
53-
renderBatch?: (browserRendererId: number, batchAddress: Pointer) => void,
54-
getConfig?: (dotNetFileName: System_String) => System_Object | undefined,
55-
getApplicationEnvironment?: () => System_String,
56-
dotNetCriticalError?: any
57-
loadLazyAssembly?: any,
58-
loadSatelliteAssemblies?: any,
59-
sendJSDataStream?: (data: any, streamId: number, chunkSize: number) => void,
60-
getJSDataStreamChunk?: (data: any, position: number, chunkSize: number) => Promise<Uint8Array>,
61-
receiveDotNetDataStream?: (streamId: number, data: any, bytesRead: number, errorMessage: string) => void,
62-
attachWebRendererInterop?: typeof attachWebRendererInterop,
53+
renderBatch?: (browserRendererId: number, batchAddress: Pointer) => void;
54+
getConfig?: (fileName: string) => Uint8Array | undefined;
55+
getApplicationEnvironment?: () => string;
56+
dotNetCriticalError?: any;
57+
loadLazyAssembly?: any;
58+
loadSatelliteAssemblies?: any;
59+
sendJSDataStream?: (data: any, streamId: number, chunkSize: number) => void;
60+
getJSDataStreamChunk?: (data: any, position: number, chunkSize: number) => Promise<Uint8Array>;
61+
receiveDotNetDataStream?: (streamId: number, data: any, bytesRead: number, errorMessage: string) => void;
62+
attachWebRendererInterop?: typeof attachWebRendererInterop;
63+
64+
// JSExport APIs
65+
dotNetExports?: {
66+
InvokeDotNet: (assemblyName: string | null, methodIdentifier: string, dotNetObjectId: number, argsJson: string) => string | null;
67+
EndInvokeJS: (argsJson: string) => void;
68+
BeginInvokeDotNet: (callId: string | null, assemblyNameOrDotNetObjectId: string, methodIdentifier: string, argsJson: string) => void;
69+
ReceiveByteArrayFromJS: (id: number, data: Uint8Array) => void;
70+
}
6371

6472
// APIs invoked by hot reload
65-
applyHotReload?: (id: string, metadataDelta: string, ilDelta: string, pdbDelta: string | undefined) => void,
66-
getApplyUpdateCapabilities?: () => string,
73+
applyHotReload?: (id: string, metadataDelta: string, ilDelta: string, pdbDelta: string | undefined) => void;
74+
getApplyUpdateCapabilities?: () => string;
6775
}
6876
}
6977

src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ async function createRuntimeInstance(resourceLoader: WebAssemblyResourceLoader):
369369
setModuleImports('blazor-internal', {
370370
Blazor: { _internal: Blazor._internal },
371371
});
372+
const exports = await runtime.getAssemblyExports('Microsoft.AspNetCore.Components.WebAssembly');
373+
Object.assign(Blazor._internal, {
374+
dotNetExports: {
375+
...exports.Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime,
376+
},
377+
});
372378
attachInteropInvoker();
373379
if (resourceLoader.bootConfig.debugBuild && resourceLoader.bootConfig.cacheBootResources) {
374380
resourceLoader.logToConsole();
@@ -412,7 +418,6 @@ async function loadSatelliteAssemblies(resourceLoader: WebAssemblyResourceLoader
412418
}));
413419
}
414420

415-
416421
async function loadLazyAssembly(resourceLoader: WebAssemblyResourceLoader, assemblyNameToLoad: string): Promise<{ dll: Uint8Array, pdb: Uint8Array | null }> {
417422
const resources = resourceLoader.bootConfig.resources;
418423
const lazyAssemblies = resources.lazyAssembly;
@@ -449,19 +454,7 @@ function getArrayDataPointer<T>(array: System_Array<T>): number {
449454
return <number><any>array + 12; // First byte from here is length, then following bytes are entries
450455
}
451456

452-
function bindStaticMethod(assembly: string, typeName: string, method: string) {
453-
// Fully qualified name looks like this: "[debugger-test] Math:IntAdd"
454-
const fqn = `[${assembly}] ${typeName}:${method}`;
455-
return BINDING.bind_static_method(fqn);
456-
}
457-
458-
export let byteArrayBeingTransferred: Uint8Array | null = null;
459457
function attachInteropInvoker(): void {
460-
const dotNetDispatcherInvokeMethodHandle = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime', 'InvokeDotNet');
461-
const dotNetDispatcherBeginInvokeMethodHandle = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime', 'BeginInvokeDotNet');
462-
const dotNetDispatcherEndInvokeJSMethodHandle = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime', 'EndInvokeJS');
463-
const dotNetDispatcherNotifyByteArrayAvailableMethodHandle = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime', 'NotifyByteArrayAvailable');
464-
465458
DotNet.attachDispatcher({
466459
beginInvokeDotNetFromJS: (callId: number, assemblyName: string | null, methodIdentifier: string, dotNetObjectId: any | null, argsJson: string): void => {
467460
assertHeapIsNotLocked();
@@ -474,26 +467,25 @@ function attachInteropInvoker(): void {
474467
? dotNetObjectId.toString()
475468
: assemblyName;
476469

477-
dotNetDispatcherBeginInvokeMethodHandle(
470+
Blazor._internal.dotNetExports!.BeginInvokeDotNet!(
478471
callId ? callId.toString() : null,
479472
assemblyNameOrDotNetObjectId,
480473
methodIdentifier,
481474
argsJson,
482475
);
483476
},
484477
endInvokeJSFromDotNet: (asyncHandle, succeeded, serializedArgs): void => {
485-
dotNetDispatcherEndInvokeJSMethodHandle(serializedArgs);
478+
Blazor._internal.dotNetExports!.EndInvokeJS(serializedArgs);
486479
},
487480
sendByteArray: (id: number, data: Uint8Array): void => {
488-
byteArrayBeingTransferred = data;
489-
dotNetDispatcherNotifyByteArrayAvailableMethodHandle(id);
481+
Blazor._internal.dotNetExports!.ReceiveByteArrayFromJS(id, data);
490482
},
491483
invokeDotNetFromJS: (assemblyName, methodIdentifier, dotNetObjectId, argsJson) => {
492484
assertHeapIsNotLocked();
493-
return dotNetDispatcherInvokeMethodHandle(
485+
return Blazor._internal.dotNetExports!.InvokeDotNet(
494486
assemblyName ? assemblyName : null,
495487
methodIdentifier,
496-
dotNetObjectId ? dotNetObjectId.toString() : null,
488+
dotNetObjectId ?? 0,
497489
argsJson,
498490
) as string;
499491
},

src/Components/Web.JS/src/Platform/WebAssemblyConfigLoader.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,19 @@
33

44
import { BootConfigResult } from './BootConfig';
55
import { WebAssemblyStartOptions } from './WebAssemblyStartOptions';
6-
import { System_String, System_Object } from './Platform';
76
import { Blazor } from '../GlobalExports';
8-
import { BINDING } from './Mono/MonoPlatform';
97

108
export class WebAssemblyConfigLoader {
119
static async initAsync(bootConfigResult: BootConfigResult, startOptions: Partial<WebAssemblyStartOptions>): Promise<void> {
12-
Blazor._internal.getApplicationEnvironment = () => BINDING.js_string_to_mono_string(bootConfigResult.applicationEnvironment);
10+
Blazor._internal.getApplicationEnvironment = () => bootConfigResult.applicationEnvironment;
1311

1412
const configFiles = await Promise.all((bootConfigResult.bootConfig.config || [])
1513
.filter(name => name === 'appsettings.json' || name === `appsettings.${bootConfigResult.applicationEnvironment}.json`)
1614
.map(async name => ({ name, content: await getConfigBytes(name) })));
1715

18-
Blazor._internal.getConfig = (dotNetFileName: System_String) : System_Object | undefined => {
19-
const fileName = BINDING.conv_string(dotNetFileName);
16+
Blazor._internal.getConfig = (fileName: string) : Uint8Array | undefined => {
2017
const resolvedFile = configFiles.find(f => f.name === fileName);
21-
return resolvedFile ? BINDING.js_typed_array_to_array(resolvedFile.content) : undefined;
18+
return resolvedFile ? resolvedFile.content : undefined;
2219
};
2320

2421
async function getConfigBytes(file: string): Promise<Uint8Array> {

src/Components/Web/src/Forms/InputFile.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ public class InputFile : ComponentBase, IInputFileJsCallbacks, IDisposable
1414
{
1515
private ElementReference _inputFileElement;
1616

17-
private IJSUnmarshalledRuntime? _jsUnmarshalledRuntime;
18-
1917
private InputFileJsCallbacksRelay? _jsCallbacksRelay;
2018

2119
[Inject]
@@ -46,12 +44,6 @@ public ElementReference? Element
4644
protected set => _inputFileElement = value!.Value;
4745
}
4846

49-
/// <inheritdoc/>
50-
protected override void OnInitialized()
51-
{
52-
_jsUnmarshalledRuntime = JSRuntime as IJSUnmarshalledRuntime;
53-
}
54-
5547
/// <inheritdoc/>
5648
protected override async Task OnAfterRenderAsync(bool firstRender)
5749
{

src/Components/Web/src/PublicAPI.Unshipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#nullable enable
2+
*REMOVED*override Microsoft.AspNetCore.Components.Forms.InputFile.OnInitialized() -> void
23
Microsoft.AspNetCore.Components.Web.HtmlComponent
34
Microsoft.AspNetCore.Components.Web.HtmlComponent.ToHtmlString() -> string!
45
Microsoft.AspNetCore.Components.Web.HtmlComponent.WaitForQuiescenceAsync() -> System.Threading.Tasks.Task!

src/Components/WebAssembly/JSInterop/src/InternalCalls.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,36 @@
33

44
using System.Diagnostics.CodeAnalysis;
55
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices.JavaScript;
67

78
namespace WebAssembly.JSInterop;
89

9-
/// <summary>
10-
/// Methods that map to the functions compiled into the Mono WebAssembly runtime,
11-
/// as defined by 'mono_add_internal_call' calls in driver.c.
12-
/// </summary>
13-
internal static class InternalCalls
10+
internal static partial class InternalCalls
1411
{
15-
// The exact namespace, type, and method names must match the corresponding entries
16-
// in driver.c in the Mono distribution
17-
/// See: https://github.com/mono/mono/blob/90574987940959fe386008a850982ea18236a533/sdks/wasm/src/driver.c#L318-L319
18-
12+
// This method only exists for backwards compatibility and will be removed in the future.
13+
// The exact namespace, type, and method name must match the corresponding entries
14+
// in driver.c in the Mono distribution.
15+
// See: https://github.com/mono/mono/blob/90574987940959fe386008a850982ea18236a533/sdks/wasm/src/driver.c#L318-L319
1916
[MethodImpl(MethodImplOptions.InternalCall)]
17+
[Obsolete]
2018
public static extern TRes InvokeJS<T0, T1, T2, TRes>(out string exception, ref JSCallInfo callInfo, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
19+
20+
[JSImport("Blazor._internal.invokeJSJson", "blazor-internal")]
21+
public static partial string InvokeJSJson(
22+
string identifier,
23+
[JSMarshalAs<JSType.Number>] long targetInstanceId,
24+
int resultType,
25+
string argsJson,
26+
[JSMarshalAs<JSType.Number>] long asyncHandle);
27+
28+
[JSImport("Blazor._internal.endInvokeDotNetFromJS", "blazor-internal")]
29+
public static partial void EndInvokeDotNetFromJS(
30+
string? id,
31+
bool success,
32+
string jsonOrError);
33+
34+
[JSImport("Blazor._internal.receiveByteArray", "blazor-internal")]
35+
public static partial void ReceiveByteArray(
36+
int id,
37+
byte[] data);
2138
}

src/Components/WebAssembly/JSInterop/src/Microsoft.JSInterop.WebAssembly.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<IsShippingPackage>true</IsShippingPackage>
99
<Nullable>enable</Nullable>
1010
<IsTrimmable>true</IsTrimmable>
11+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1112
<!-- TODO: Address Native AOT analyzer warnings https://github.com/dotnet/aspnetcore/issues/45473 -->
1213
<EnableAOTAnalyzer>false</EnableAOTAnalyzer>
1314
</PropertyGroup>

0 commit comments

Comments
 (0)