Aspnetcore: Crash on js interop `hasOwnProperty`

Created on 28 Jun 2020  路  5Comments  路  Source: dotnet/aspnetcore

Describe the bug

I'm using IJSRuntime to detect the presence of a value:

//[Inject] private IJSRuntime js {get;set;}
// assume foo is undefined so far
await js.InvokeAsync<bool>("hasOwnProperty", "foo");

A subsequent call to e.g. "alert" or "eval" then fails:

await js.InvokeVoidAsync("alert", "hello");

My expectation is that this should never fail.

To Reproduce

@page "/undefined_value"
@inject IJSRuntime js
@using Microsoft.Extensions.Logging
@inject ILogger<Index> logger;

<button @onclick="RunBug">Run Bug</button>

@code {
    private async Task RunBug()
    {
        logger.LogInformation("before checking");
        await js.InvokeAsync<bool>("hasOwnProperty", "foo");
        logger.LogInformation("after checking");
        logger.LogInformation("before setting");
        await js.InvokeVoidAsync("eval", "window.foo = 'bar'");
        logger.LogInformation("after setting");
    }
}

When the value is already set before, no error occurs:

@page "/set_before"
@inject IJSRuntime js
@using Microsoft.Extensions.Logging
@inject ILogger<Index> logger;

<button @onclick="RunBugfree">Run without bug</button>

@code {
    private async Task RunBugfree()
    {
        logger.LogInformation("before setting");
        await js.InvokeVoidAsync("eval", "window.baz = 'bar'");
        logger.LogInformation("after setting");
        logger.LogInformation("before checking");
        await js.InvokeAsync<bool>("hasOwnProperty", "baz");
        logger.LogInformation("after checking");
        logger.LogInformation("before setting again");
        await js.InvokeVoidAsync("eval", "window.baz = 'bar2'");
        logger.LogInformation("after setting again");
    }
}

Exceptions (if any)

warn: Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer[100]
      Unhandled exception rendering component: Cannot read property 'apply' of undefined
TypeError: Cannot read property 'apply' of undefined
    at https://localhost:5001/_framework/blazor.server.js:8:31420
    at new Promise (<anonymous>)
    at e.beginInvokeJSFromDotNet (https://localhost:5001/_framework/blazor.server.js:8:31390)
    at https://localhost:5001/_framework/blazor.server.js:1:19202
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (https://localhost:5001/_framework/blazor.server.js:1:19173)
    at e.processIncomingData (https://localhost:5001/_framework/blazor.server.js:1:17165)
    at e.connection.onreceive (https://localhost:5001/_framework/blazor.server.js:1:10276)
    at WebSocket.i.onmessage (https://localhost:5001/_framework/blazor.server.js:1:38091)
Microsoft.JSInterop.JSException: Cannot read property 'apply' of undefined
TypeError: Cannot read property 'apply' of undefined
    at https://localhost:5001/_framework/blazor.server.js:8:31420
    at new Promise (<anonymous>)
    at e.beginInvokeJSFromDotNet (https://localhost:5001/_framework/blazor.server.js:8:31390)
    at https://localhost:5001/_framework/blazor.server.js:1:19202
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (https://localhost:5001/_framework/blazor.server.js:1:19173)
    at e.processIncomingData (https://localhost:5001/_framework/blazor.server.js:1:17165)
    at e.connection.onreceive (https://localhost:5001/_framework/blazor.server.js:1:10276)
    at WebSocket.i.onmessage (https://localhost:5001/_framework/blazor.server.js:1:38091)
   at Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation[T](String identifier, Object[] args)
   at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync(IJSRuntime jsRuntime, String identifier, Object[] args)
   at BlazorApp.Index.RunBug() in C:\path_to\somefile.razor:line 16
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Further technical details

  • .NET Core SDK (3.1.301)
Done area-blazor

Most helpful comment

@stefanloerwald In the meantime, as a workaround, you can do:

await js.InvokeAsync<bool>("window.hasOwnProperty", "foo");

(i.e., add the window. prefix)

All 5 comments

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we will planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

Thanks for reporting this! I've filed a PR with a fix at https://github.com/dotnet/aspnetcore/pull/23573

Thanks @SteveSandersonMS for already providing a fix! I'm glad it was a one-liner and not much more work.

@stefanloerwald In the meantime, as a workaround, you can do:

await js.InvokeAsync<bool>("window.hasOwnProperty", "foo");

(i.e., add the window. prefix)

Was this page helpful?
0 / 5 - 0 ratings