Skip to content

The IJSObjectReference.Invoke implementation does not support Javascript properties (i.e. getters and setters) #25756

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

Closed
JinShil opened this issue Sep 10, 2020 · 5 comments
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-jsinterop This issue is related to JSInterop in Blazor ✔️ Resolution: Duplicate Resolved as a duplicate of another issue severity-nice-to-have This label is used by an internal tool Status: Resolved
Milestone

Comments

@JinShil
Copy link

JinShil commented Sep 10, 2020

Describe the bug

The IJSObjectReference.Invoke implementation does not support javascript properties (i.e. getters and setters). Since properties are simply encapsulated functions, I think we should be able to read properties with IJSObjectReference.Invoke<PropertyType>("propertyName") and write properties with IJSObjectReference.InvokeVoid("propertyName", value);

To Reproduce

@inject IJSRuntime JS

<button class="btn btn-primary" @onclick="GetLocation">Get Location</button>

<div>@_location</div>

@code {
    string _location;

    private void GetLocation()
    {
        _location = _window.Invoke<string>("location"); // Error here
    }

    IJSInProcessObjectReference _window;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        if (firstRender)
        {
            _window = ((IJSInProcessRuntime)JS).Invoke<IJSInProcessObjectReference>("interop.getWindow");
        }
    }
}

Exceptions (if any)

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: The value 'location' is not a function.
      Error: The value 'location' is not a function.
          at e.findFunction (http://localhost:21659/_framework/blazor.webassembly.js:1:1442)
          at b (http://localhost:21659/_framework/blazor.webassembly.js:1:2989)
          at Object.invokeJSFromDotNet (http://localhost:21659/_framework/blazor.webassembly.js:1:3790)
          at Object.w [as invokeJSFromDotNet] (http://localhost:21659/_framework/blazor.webassembly.js:1:60466)
          at _mono_wasm_invoke_js_blazor (http://localhost:21659/_framework/dotnet.5.0.0-rc.1.20431.14.js:1:183003)
          at do_icall (<anonymous>:wasm-function[10583]:0x1944fd)
          at do_icall_wrapper (<anonymous>:wasm-function[3296]:0x79894)
          at interp_exec_method (<anonymous>:wasm-function[2147]:0x4442c)
          at interp_runtime_invoke (<anonymous>:wasm-function[7851]:0x12e8ab)
          at mono_jit_runtime_invoke (<anonymous>:wasm-function[7334]:0x118342)
Microsoft.JSInterop.JSException: The value 'location' is not a function.
Error: The value 'location' is not a function.
    at e.findFunction (http://localhost:21659/_framework/blazor.webassembly.js:1:1442)
    at b (http://localhost:21659/_framework/blazor.webassembly.js:1:2989)
    at Object.invokeJSFromDotNet (http://localhost:21659/_framework/blazor.webassembly.js:1:3790)
    at Object.w [as invokeJSFromDotNet] (http://localhost:21659/_framework/blazor.webassembly.js:1:60466)
    at _mono_wasm_invoke_js_blazor (http://localhost:21659/_framework/dotnet.5.0.0-rc.1.20431.14.js:1:183003)
    at do_icall (<anonymous>:wasm-function[10583]:0x1944fd)
    at do_icall_wrapper (<anonymous>:wasm-function[3296]:0x79894)
    at interp_exec_method (<anonymous>:wasm-function[2147]:0x4442c)
    at interp_runtime_invoke (<anonymous>:wasm-function[7851]:0x12e8ab)
    at mono_jit_runtime_invoke (<anonymous>:wasm-function[7334]:0x118342)
   at Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.InvokeJS(String identifier, String argsJson, JSCallResultType resultType, Int64 targetInstanceId)
   at Microsoft.JSInterop.JSInProcessRuntime.Invoke[String](String identifier, Int64 targetInstanceId, Object[] args)
   at Microsoft.JSInterop.Implementation.JSInProcessObjectReference.Invoke[String](String identifier, Object[] args)
   at Test.Pages.Counter.GetLocation() in C:\Users\Mike\Desktop\Test\Test\Pages\Counter.razor:line 14
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync[Object](MulticastDelegate delegate, Object arg)
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync(Object arg)
   at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, Object arg)
   at Microsoft.AspNetCore.Components.EventCallback.InvokeAsync(Object arg)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync(UInt64 eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs)

Further technical details

dotnet --version
5.0.100-rc.2.20454.3
dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.100-rc.2.20454.3
 Commit:    1e40c01301

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19041
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.100-rc.2.20454.3\

Host (useful for support):
  Version: 5.0.0-rc.1.20431.14
  Commit:  3bcbbd5b74

.NET SDKs installed:
  2.1.302 [C:\Program Files\dotnet\sdk]
  2.1.401 [C:\Program Files\dotnet\sdk]
  2.1.402 [C:\Program Files\dotnet\sdk]
  2.1.403 [C:\Program Files\dotnet\sdk]
  2.1.503 [C:\Program Files\dotnet\sdk]
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.604 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  3.0.100-preview9-014004 [C:\Program Files\dotnet\sdk]
  3.0.100 [C:\Program Files\dotnet\sdk]
  3.1.200 [C:\Program Files\dotnet\sdk]
  3.1.302 [C:\Program Files\dotnet\sdk]
  5.0.100-preview.8.20417.9 [C:\Program Files\dotnet\sdk]
  5.0.100-rc.1.20454.5 [C:\Program Files\dotnet\sdk]
  5.0.100-rc.2.20454.3 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview9.19424.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0-preview.8.20414.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0-rc.1.20451.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview9-19423-09 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0-preview.8.20407.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0-rc.1.20431.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview9-19423-09 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0-preview.8.20411.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0-rc.1.20431.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
@javiercn javiercn added the area-blazor Includes: Blazor, Razor Components label Sep 10, 2020
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Sep 10, 2020
@mkArtakMSFT mkArtakMSFT added this to the Backlog milestone Sep 10, 2020
@ghost
Copy link

ghost commented Sep 10, 2020

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@pranavkm pranavkm added affected-most This issue impacts most of the customers severity-minor This label is used by an internal tool labels Oct 5, 2020
@javiercn javiercn added the feature-blazor-jsinterop This issue is related to JSInterop in Blazor label Apr 20, 2021
@user72356
Copy link

user72356 commented Sep 9, 2021

I've hit that same issue recently while wrapping a JS lib in Blazor. I have a workaround, it's an ugly hack but that is all we have at the moment...

Add these to your .js file, it will change the prototype for the Object type in JS, akin to extensions methods in C#. It's apparently not recommended due to potential performance issues since we're changing objects mid-way through the execution. Any JS engine optimizations that expect a certain object shape could be affected by that.

Object.defineProperty(Object.prototype, "getProperty",
{
    value: function getProperty(key)
    {
        return this[key];
    },
    writable: true,
    configurable: true
});
Object.defineProperty(Object.prototype, "setProperty",
{
    value: function setProperty(key, value)
    {
        this[key] = value;
    },
    writable: true,
    configurable: true
});

Now you can invoke getProperty and setProperty from the .Net side.

public string Target
{
    get => jsRef.Invoke<string>("getProperty", "target");
}

@TanayParikh TanayParikh added severity-nice-to-have This label is used by an internal tool and removed severity-minor This label is used by an internal tool labels Oct 19, 2021
@rummelsworth
Copy link

This seems pretty severe to me. The current situation seems to be this: it's impossible to cleanly and idiomatically access a JS object's properties through the lens of IJSObjectReference. That seems like a weirdly huge gap in functionality.

I don't control the definition of the object whose property I need, so unless I use the workaround mentioned above or something like it, I'm well up the proverbial creek.

@KristofferStrube
Copy link
Contributor

The progress on solving this problem is also kept track of in issue #31151 in the third Task of the issue.

@danroth27 danroth27 added the ✔️ Resolution: Duplicate Resolved as a duplicate of another issue label Oct 13, 2022
@ghost ghost added the Status: Resolved label Oct 13, 2022
@danroth27
Copy link
Member

Closing, as this is being tracked as part of #31151

@ghost ghost locked as resolved and limited conversation to collaborators Nov 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-jsinterop This issue is related to JSInterop in Blazor ✔️ Resolution: Duplicate Resolved as a duplicate of another issue severity-nice-to-have This label is used by an internal tool Status: Resolved
Projects
None yet
Development

No branches or pull requests

9 participants