Skip to content
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

[blazor] Obsolete InvokeUnmarshalled #42814

Merged
merged 4 commits into from
Jul 20, 2022
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
258 changes: 239 additions & 19 deletions src/Components/Web.JS/@types/dotnet/dotnet.d.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Components/Web.JS/src/Boot.WebAssembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
jsInitializer.invokeAfterStartedCallbacks(Blazor);
}

// obsolete, legacy, don't use for new code!
function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any {
const functionIdentifier = monoPlatform.readStringField(callInfo, 0)!;
const resultType = monoPlatform.readInt32Field(callInfo, 4);
Expand Down
22 changes: 16 additions & 6 deletions src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DotnetPublicAPI, BINDINGType, CreateDotnetRuntimeType, DotnetModuleConf
export let BINDING: BINDINGType = undefined as any;
export let MONO: MONOType = undefined as any;
export let Module: DotnetModuleConfig & EmscriptenModule = undefined as any;
export let IMPORTS: any = undefined as any;

const appBinDirName = 'appBinDir';
const uint64HighOrderShift = Math.pow(2, 32);
Expand Down Expand Up @@ -286,18 +287,19 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc
const createDotnetRuntime = await dotnetJsBeingLoaded;

await createDotnetRuntime((api) => {
const { MONO: mono, BINDING: binding, Module: module } = api;
const { MONO: mono, BINDING: binding, Module: module, IMPORTS: imports } = api;
Module = module;
BINDING = binding;
MONO = mono;
IMPORTS = imports;

// Override the mechanism for fetching the main wasm file so we can connect it to our cache
const instantiateWasm = (imports, successCallback) => {
const instantiateWasm = (wasmImports, successCallback) => {
(async () => {
let compiledInstance: WebAssembly.Instance;
try {
const dotnetWasmResource = await wasmBeingLoaded;
compiledInstance = await compileWasmModule(dotnetWasmResource, imports);
compiledInstance = await compileWasmModule(dotnetWasmResource, wasmImports);
} catch (ex) {
printErr((ex as Error).toString());
throw ex;
Expand Down Expand Up @@ -329,9 +331,7 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc
assembliesBeingLoaded.forEach(r => addResourceAsAssembly(r, changeExtension(r.name, '.dll')));
pdbsBeingLoaded.forEach(r => addResourceAsAssembly(r, r.name));

Blazor._internal.dotNetCriticalError = (message) => {
printErr(BINDING.conv_string(message) || '(null)');
};
Blazor._internal.dotNetCriticalError = (message) => printErr(message || '(null)');

// Wire-up callbacks for satellite assemblies. Blazor will call these as part of the application
// startup sequence to load satellite assemblies for the application's culture.
Expand Down Expand Up @@ -467,6 +467,16 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc
// -1 enables debugging with logging disabled. 0 disables debugging entirely.
MONO.mono_wasm_load_runtime(appBinDirName, hasDebuggingEnabled() ? -1 : 0);
MONO.mono_wasm_runtime_ready();
try {
BINDING.bind_static_method('invalid-fqn', '');
} catch (e) {
// HOTFIX: until https://github.com/dotnet/runtime/pull/72275
// this would always throw, but it will initialize runtime interop as side-effect
}

// makes Blazor._internal visible to [JSImport]
IMPORTS.Blazor = { _internal: Blazor._internal };

attachInteropInvoker();
runtimeReadyResolve(api);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,37 @@ public WebAssemblyJSObjectReference(WebAssemblyJSRuntime jsRuntime, long id)
_jsRuntime = jsRuntime;
}

#pragma warning disable CS0612 // Type or member is obsolete
[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
SteveSandersonMS marked this conversation as resolved.
Show resolved Hide resolved
public TResult InvokeUnmarshalled<TResult>(string identifier)
{
ThrowIfDisposed();

return _jsRuntime.InvokeUnmarshalled<object?, object?, object?, TResult>(identifier, null, null, null, Id);
}

[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
{
ThrowIfDisposed();

return _jsRuntime.InvokeUnmarshalled<T0, object?, object?, TResult>(identifier, arg0, null, null, Id);
}

[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
{
ThrowIfDisposed();

return _jsRuntime.InvokeUnmarshalled<T0, T1, object?, TResult>(identifier, arg0, arg1, null, Id);
}

[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
{
ThrowIfDisposed();

return _jsRuntime.InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2, Id);
}
#pragma warning restore CS0612 // Type or member is obsolete
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,21 @@ protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNet
var resultJsonOrErrorMessage = dispatchResult.Success
? dispatchResult.ResultJson!
: dispatchResult.Exception!.ToString();
#pragma warning disable CS0618 // Type or member is obsolete
InvokeUnmarshalled<string?, bool, string, object>("Blazor._internal.endInvokeDotNetFromJS",
callInfo.CallId, dispatchResult.Success, resultJsonOrErrorMessage);
#pragma warning restore CS0618 // Type or member is obsolete
}

/// <inheritdoc />
protected override void SendByteArray(int id, byte[] data)
{
#pragma warning disable CS0618 // Type or member is obsolete
InvokeUnmarshalled<int, byte[], object>("Blazor._internal.receiveByteArray", id, data);
#pragma warning restore CS0618 // Type or member is obsolete
}

[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
SteveSandersonMS marked this conversation as resolved.
Show resolved Hide resolved
internal TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2, long targetInstanceId)
{
var resultType = JSCallResultTypeHelper.FromGeneric<TResult>();
Expand Down Expand Up @@ -122,18 +127,22 @@ private IJSStreamReference DeserializeJSStreamReference(string serializedStreamR
}

/// <inheritdoc />
[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<TResult>(string identifier)
=> InvokeUnmarshalled<object?, object?, object?, TResult>(identifier, null, null, null, 0);

/// <inheritdoc />
[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
=> InvokeUnmarshalled<T0, object?, object?, TResult>(identifier, arg0, null, null, 0);

/// <inheritdoc />
[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
=> InvokeUnmarshalled<T0, T1, object?, TResult>(identifier, arg0, arg1, null, 0);

/// <inheritdoc />
[Obsolete("This method is obsolete. Use JSImportAttribute instead.")]
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
=> InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2, 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public virtual async ValueTask LoadCurrentCultureResourcesAsync()
// assemblies. We effectively want to resovle a Task<byte[][]> but there is no way to express this
// using interop. We'll instead do this in two parts:
// getSatelliteAssemblies resolves when all satellite assemblies to be loaded in .NET are fetched and available in memory.
#pragma warning disable CS0618 // Type or member is obsolete
var count = (int)await _invoker.InvokeUnmarshalled<string[], object?, object?, Task<object>>(
GetSatelliteAssemblies,
culturesToLoad.ToArray(),
Expand All @@ -91,6 +92,7 @@ public virtual async ValueTask LoadCurrentCultureResourcesAsync()
null,
null,
null);
#pragma warning restore CS0618 // Type or member is obsolete

for (var i = 0; i < assemblies.Length; i++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal WebAssemblyHostBuilder(IJSUnmarshalledRuntime jsRuntime, JsonSerializer
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Root components are expected to be defined in assemblies that do not get trimmed.")]
private void InitializeRegisteredRootComponents(IJSUnmarshalledRuntime jsRuntime)
{
#pragma warning disable CS0618 // Type or member is obsolete
var componentsCount = jsRuntime.InvokeUnmarshalled<int>(RegisteredComponentsInterop.GetRegisteredComponentsCount);
if (componentsCount == 0)
{
Expand All @@ -106,6 +107,7 @@ private void InitializeRegisteredRootComponents(IJSUnmarshalledRuntime jsRuntime
var serializedParameterValues = jsRuntime.InvokeUnmarshalled<int, object?, object?, string>(RegisteredComponentsInterop.GetParameterValues, id, null, null);
registeredComponents[i] = new WebAssemblyComponentMarker(WebAssemblyComponentMarker.ClientMarkerType, assembly, typeName, serializedParameterDefinitions, serializedParameterValues, id.ToString(CultureInfo.InvariantCulture));
}
#pragma warning restore CS0618 // Type or member is obsolete

var componentDeserializer = WebAssemblyComponentParameterDeserializer.Instance;
foreach (var registeredComponent in registeredComponents)
Expand All @@ -129,20 +131,26 @@ private void InitializeRegisteredRootComponents(IJSUnmarshalledRuntime jsRuntime

private void InitializePersistedState(IJSUnmarshalledRuntime jsRuntime)
{
#pragma warning disable CS0618 // Type or member is obsolete
_persistedState = jsRuntime.InvokeUnmarshalled<string>("Blazor._internal.getPersistedState");
#pragma warning restore CS0618 // Type or member is obsolete
}

private static void InitializeNavigationManager(IJSUnmarshalledRuntime jsRuntime)
{
#pragma warning disable CS0618 // Type or member is obsolete
var baseUri = jsRuntime.InvokeUnmarshalled<string>(BrowserNavigationManagerInterop.GetBaseUri);
var uri = jsRuntime.InvokeUnmarshalled<string>(BrowserNavigationManagerInterop.GetLocationHref);
#pragma warning restore CS0618 // Type or member is obsolete

WebAssemblyNavigationManager.Instance = new WebAssemblyNavigationManager(baseUri, uri);
}

private WebAssemblyHostEnvironment InitializeEnvironment(IJSUnmarshalledRuntime jsRuntime)
{
#pragma warning disable CS0618 // Type or member is obsolete
var applicationEnvironment = jsRuntime.InvokeUnmarshalled<string>("Blazor._internal.getApplicationEnvironment");
#pragma warning restore CS0618 // Type or member is obsolete
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment, WebAssemblyNavigationManager.Instance.BaseUri);

Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
Expand All @@ -155,8 +163,10 @@ private WebAssemblyHostEnvironment InitializeEnvironment(IJSUnmarshalledRuntime

foreach (var configFile in configFiles)
{
#pragma warning disable CS0618 // Type or member is obsolete
var appSettingsJson = jsRuntime.InvokeUnmarshalled<string, byte[]>(
"Blazor._internal.getConfig", configFile);
#pragma warning restore CS0618 // Type or member is obsolete

if (appSettingsJson != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ internal static async Task InitializeAsync()
// See https://github.com/dotnet/aspnetcore/issues/37357#issuecomment-941237000

var jsObjectReference = (IJSUnmarshalledObjectReference)(await DefaultWebAssemblyJSRuntime.Instance.InvokeAsync<IJSObjectReference>("import", "/_framework/blazor-hotreload.js"));
#pragma warning disable CS0618 // Type or member is obsolete
await jsObjectReference.InvokeUnmarshalled<Task<int>>("receiveHotReload");
#pragma warning restore CS0618 // Type or member is obsolete
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<IsTrimmable>true</IsTrimmable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ protected override void ProcessPendingRender()
/// <inheritdoc />
protected override Task UpdateDisplayAsync(in RenderBatch batch)
{
#pragma warning disable CS0618 // Type or member is obsolete
DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<int, RenderBatch, object>(
"Blazor._internal.renderBatch",
RendererId,
batch);
#pragma warning restore CS0618 // Type or member is obsolete

if (WebAssemblyCallQueue.HasUnstartedWork)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ public static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetO
/// <param name="id">Id of the byte array</param>
public static void NotifyByteArrayAvailable(int id)
{
#pragma warning disable CS0618 // Type or member is obsolete
var data = Instance.InvokeUnmarshalled<byte[]>("Blazor._internal.retrieveByteArray");
#pragma warning restore CS0618 // Type or member is obsolete

DotNetDispatcher.ReceiveByteArray(Instance, id, data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,22 @@ private async Task<IEnumerable<Assembly>> LoadAssembliesInClientAsync(IEnumerabl
}

var jsRuntime = (IJSUnmarshalledRuntime)_jsRuntime;
#pragma warning disable CS0618 // Type or member is obsolete
var count = (int)await jsRuntime.InvokeUnmarshalled<string[], Task<object>>(
GetLazyAssemblies,
newAssembliesToLoad.ToArray());
#pragma warning restore CS0618 // Type or member is obsolete

if (count == 0)
{
return Array.Empty<Assembly>();
}

var loadedAssemblies = new List<Assembly>();
#pragma warning disable CS0618 // Type or member is obsolete
var assemblies = jsRuntime.InvokeUnmarshalled<byte[][]>(ReadLazyAssemblies);
var pdbs = jsRuntime.InvokeUnmarshalled<byte[][]>(ReadLazyPDBs);
#pragma warning restore CS0618 // Type or member is obsolete

for (int i = 0; i < assemblies.Length; i++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Runtime.InteropServices.JavaScript;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
Expand Down Expand Up @@ -79,19 +80,19 @@ private void WriteMessage(LogLevel logLevel, string logName, int eventId, string
// messages if you enable "Verbose" in the filter dropdown (which is off
// by default). As such "console.debug" is the best choice for messages
// with a lower severity level than "Information".
_jsRuntime.InvokeVoid("console.debug", formattedMessage);
ConsoleLoggerInterop.ConsoleDebug(formattedMessage);
break;
case LogLevel.Information:
_jsRuntime.InvokeVoid("console.info", formattedMessage);
ConsoleLoggerInterop.ConsoleInfo(formattedMessage);
break;
case LogLevel.Warning:
_jsRuntime.InvokeVoid("console.warn", formattedMessage);
ConsoleLoggerInterop.ConsoleWarn(formattedMessage);
break;
case LogLevel.Error:
_jsRuntime.InvokeVoid("console.error", formattedMessage);
ConsoleLoggerInterop.ConsoleError(formattedMessage);
break;
case LogLevel.Critical:
_jsRuntime.InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
ConsoleLoggerInterop.DotNetCriticalError(formattedMessage);
break;
default: // invalid enum values
Debug.Assert(logLevel != LogLevel.None, "This method is never called with LogLevel.None.");
Expand Down Expand Up @@ -165,3 +166,17 @@ private sealed class NoOpDisposable : IDisposable
public void Dispose() { }
}
}

internal static partial class ConsoleLoggerInterop
{
[JSImport("globalThis.console.debug")]
public static partial void ConsoleDebug(string message);
[JSImport("globalThis.console.info")]
public static partial void ConsoleInfo(string message);
[JSImport("globalThis.console.warn")]
public static partial void ConsoleWarn(string message);
[JSImport("globalThis.console.error")]
public static partial void ConsoleError(string message);
[JSImport("Blazor._internal.dotNetCriticalError")]
public static partial void DotNetCriticalError(string message);
}
SteveSandersonMS marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ public async Task LoadCurrentCultureResourcesAsync_ReadsAssemblies()
// Arrange
using var cultureReplacer = new CultureReplacer("en-GB");
var invoker = new Mock<IJSUnmarshalledRuntime>();
#pragma warning disable CS0618 // Type or member is obsolete
invoker.Setup(i => i.InvokeUnmarshalled<string[], object, object, Task<object>>(GetSatelliteAssemblies, new[] { "en-GB", "en" }, null, null))
.Returns(Task.FromResult<object>(1))
.Verifiable();

invoker.Setup(i => i.InvokeUnmarshalled<object, object, object, object[]>(ReadSatelliteAssemblies, null, null, null))
.Returns(new object[] { File.ReadAllBytes(GetType().Assembly.Location) })
.Verifiable();
#pragma warning restore CS0618 // Type or member is obsolete

var loader = new WebAssemblyCultureProvider(invoker.Object, CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture);

Expand All @@ -56,17 +58,21 @@ public async Task LoadCurrentCultureResourcesAsync_DoesNotReadAssembliesWhenTher
// Arrange
using var cultureReplacer = new CultureReplacer("en-GB");
var invoker = new Mock<IJSUnmarshalledRuntime>();
#pragma warning disable CS0618 // Type or member is obsolete
invoker.Setup(i => i.InvokeUnmarshalled<string[], object, object, Task<object>>(GetSatelliteAssemblies, new[] { "en-GB", "en" }, null, null))
.Returns(Task.FromResult<object>(0))
.Verifiable();
#pragma warning restore CS0618 // Type or member is obsolete

var loader = new WebAssemblyCultureProvider(invoker.Object, CultureInfo.CurrentCulture, CultureInfo.CurrentUICulture);

// Act
await loader.LoadCurrentCultureResourcesAsync();

#pragma warning disable CS0618 // Type or member is obsolete
// Assert
invoker.Verify(i => i.InvokeUnmarshalled<object, object, object, object[]>(ReadSatelliteAssemblies, null, null, null), Times.Never());
#pragma warning restore CS0618 // Type or member is obsolete
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@

// we should be able to downcast a IJSInProcessObjectReference as a IJSUnmarshalledObjectReference
var unmarshalledCast = (IJSUnmarshalledObjectReference)jsInProcObjectReference;
#pragma warning disable CS0618 // Type or member is obsolete
ReturnValues["jsCastedUnmarshalledObjectReference.unmarshalledFunction"] = unmarshalledCast.InvokeUnmarshalled<InteropStruct, bool>("unmarshalledFunction", new InteropStruct
{
Message = "Sent from .NET",
Expand All @@ -418,6 +419,7 @@


var dataReference = unmarshalledRuntime.InvokeUnmarshalled<IJSStreamReference>("jsToDotNetStreamReturnValue");
#pragma warning restore CS0618 // Type or member is obsolete
using var dataReferenceStream = await dataReference.OpenReadStreamAsync();
await ValidateStreamValuesAsync("jsToDotNetStreamReturnValueUnmarshalled", dataReferenceStream);
}
Expand Down
Loading