Skip to content

Remove Entrypoint Invoker #31769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
8 commits merged into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Components/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/Samples/**/.vscode/*
2 changes: 1 addition & 1 deletion src/Components/Web.JS/dist/Release/blazor.server.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Components/Web.JS/src/Boot.WebAssembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
}

// Start up the application
platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly);
await platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly);
Copy link
Member

@SteveSandersonMS SteveSandersonMS Apr 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TanayParikh @pranavkm Does this change the semantics of app startup? It depends on how BINDING.call_assembly_entry_point behaves, which I can't guess from reading the diff.

I thought that, previously, calling Blazor.start would return a promise that resolves when the .NET code begins running and yields the thread (e.g., on an await). Is that still how it behaves, or does it now resolve only when MainAsync's task completes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be related to the functionality of BINDING.call_assembly_entry_point specifically. Pinging @lewing for more context on this given dotnet/runtime#44045.

Copy link
Member

@lewing lewing Apr 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveSandersonMS is correct, successfully awaiting that task should give you the exit code, control will return as soon as it can, given that the runtime is currently singly threaded. If your model expects control to yield here before the runtime has exited, don't await the entry point promise. That said, any expectations that the entry point will yield at a specific point are probably weak.

Copy link
Member

@SteveSandersonMS SteveSandersonMS Apr 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @lewing

In this case, this PR is a breaking change we should fix before preview 4 ships. @TanayParikh I'll follow up separately to coordinate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any {
Expand Down
19 changes: 9 additions & 10 deletions src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,15 @@ export const monoPlatform: Platform = {
});
},

callEntryPoint: function callEntryPoint(assemblyName: string) {
// Instead of using Module.mono_call_assembly_entry_point, we have our own logic for invoking
// the entrypoint which adds support for async main.
// Currently we disregard the return value from the entrypoint, whether it's sync or async.
// In the future, we might want Blazor.start to return a Promise<Promise<value>>, where the
// outer promise reflects the startup process, and the inner one reflects the possibly-async
// .NET entrypoint method.
const invokeEntrypoint = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.EntrypointInvoker', 'InvokeEntrypoint');
// Note we're passing in null because passing arrays is problematic until https://github.com/mono/mono/issues/18245 is resolved.
invokeEntrypoint(assemblyName, null);
callEntryPoint: async function callEntryPoint(assemblyName: string) : Promise<any> {
const emptyArray = [ [ ] ];

try {
await BINDING.call_assembly_entry_point(assemblyName, emptyArray, "m")
} catch (error) {
console.error(error);
showErrorNotification();
}
},

toUint8Array: function toUint8Array(array: System_Array<any>): Uint8Array {
Expand Down
1 change: 1 addition & 0 deletions src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare interface BINDING {
mono_array_to_js_array<TInput, TOutput>(array: System_Array<TInput>) : Array<TOutput>;
conv_string(dotnetString: System_String | null): string | null;
bind_static_method(fqn: string, signature?: string): Function;
call_assembly_entry_point(assemblyName: string, args: any[], signature: any): Promise<any>;
unbox_mono_obj(object: System_Object): any;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Components/Web.JS/src/Platform/Platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { WebAssemblyResourceLoader } from './WebAssemblyResourceLoader';
export interface Platform {
start(resourceLoader: WebAssemblyResourceLoader): Promise<void>;

callEntryPoint(assemblyName: string): void;
callEntryPoint(assemblyName: string): Promise<any>;

toUint8Array(array: System_Array<any>): Uint8Array;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ public void ThrowIfCultureChangeIsUnsupported()
// incomplete icu data for their culture. We would like to flag this as an error and notify the author to
// use the combined icu data file instead.
//
// The Initialize method is invoked as one of the first steps bootstrapping the app prior to any user code running.
// The Initialize method is invoked as one of the first steps bootstrapping the app within WebAssemblyHostBuilder.CreateDefault.
// It allows us to capture the initial .NET culture that is configured based on the browser language.
// The current method is invoked as part of WebAssemblyHost.RunAsync i.e. after user code in Program.MainAsync has run
// thus allows us to detect if the culture was changed by user code.
if (Environment.GetEnvironmentVariable("__BLAZOR_SHARDED_ICU") == "1" &&
((CultureInfo.CurrentCulture != InitialCulture) || (CultureInfo.CurrentUICulture != InitialUICulture)))
((!CultureInfo.CurrentCulture.Name.Equals(InitialCulture.Name, StringComparison.Ordinal) ||
!CultureInfo.CurrentUICulture.Name.Equals(InitialUICulture.Name, StringComparison.Ordinal))))
{
throw new InvalidOperationException("Blazor detected a change in the application's culture that is not supported with the current project configuration. " +
"To change culture dynamically during startup, set <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData> in the application's project file.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ internal WebAssemblyHost(
string? persistedState)
{
// To ensure JS-invoked methods don't get linked out, have a reference to their enclosing types
GC.KeepAlive(typeof(EntrypointInvoker));
GC.KeepAlive(typeof(JSInteropMethods));

_services = services;
Expand All @@ -68,8 +67,6 @@ internal WebAssemblyHost(
/// </summary>
public IServiceProvider Services => _scope.ServiceProvider;

internal WebAssemblyCultureProvider CultureProvider { get; set; } = WebAssemblyCultureProvider.Instance!;

/// <summary>
/// Disposes the host asynchronously.
/// </summary>
Expand Down Expand Up @@ -124,7 +121,7 @@ public Task RunAsync()
}

// Internal for testing.
internal async Task RunAsyncCore(CancellationToken cancellationToken)
internal async Task RunAsyncCore(CancellationToken cancellationToken, WebAssemblyCultureProvider? cultureProvider = null)
{
if (_started)
{
Expand All @@ -133,13 +130,13 @@ internal async Task RunAsyncCore(CancellationToken cancellationToken)

_started = true;

CultureProvider.ThrowIfCultureChangeIsUnsupported();
cultureProvider ??= WebAssemblyCultureProvider.Instance!;
cultureProvider.ThrowIfCultureChangeIsUnsupported();

// EntryPointInvoker loads satellite assemblies for the application default culture.
// Application developers might have configured the culture based on some ambient state
// such as local storage, url etc as part of their Program.Main(Async).
// This is the earliest opportunity to fetch satellite assemblies for this selection.
await CultureProvider.LoadCurrentCultureResourcesAsync();
await cultureProvider.LoadCurrentCultureResourcesAsync();

var manager = Services.GetRequiredService<ComponentApplicationLifetime>();
var store = !string.IsNullOrEmpty(_persistedState) ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public sealed class WebAssemblyHostBuilder
/// </summary>
/// <param name="args">The argument passed to the application's main method.</param>
/// <returns>A <see cref="WebAssemblyHostBuilder"/>.</returns>
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(EntrypointInvoker))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(JSInteropMethods))]
[DynamicDependency(JsonSerialized, typeof(WebEventDescriptor))]
public static WebAssemblyHostBuilder CreateDefault(string[]? args = default)
Expand All @@ -46,6 +45,8 @@ public static WebAssemblyHostBuilder CreateDefault(string[]? args = default)
args ??= Array.Empty<string>();
var builder = new WebAssemblyHostBuilder(DefaultWebAssemblyJSRuntime.Instance);

WebAssemblyCultureProvider.Initialize();

// Right now we don't have conventions or behaviors that are specific to this method
// however, making this the default for the template allows us to add things like that
// in the future, while giving `new WebAssemblyHostBuilder` as an opt-out of opinionated
Expand Down

This file was deleted.

Loading