Welcome Guest Search | Active Topics | Sign In | Register

JSObject or JSFunction becomes invalid Options
AAAton
Posted: Friday, May 3, 2019 8:09:09 AM
Rank: Newbie
Groups: Member

Joined: 12/12/2018
Posts: 4
Hi!
I'm trying to invoke a JSFunction callback on a single page application (SPA) written in React in the EO.WebView.
I'm having issues with my JSObject/JSFunction pointers as they seem to become invalid at certain points.

The function is sent from JS to .NET with something like:
Code: JavaScript
window.external.SetCallback(this, functionName)

and is received on the C# side like:
Code: C#
public void SetCallback(JSObject context, JSFunction callback) {
    this.Context = context;
    this.Callback = callback;
}

When it's time to trigger the callback it's called like:
Code: C#
private void TriggerCallback(object[] args) {
    try {
        if(this.WebView.CanEvalScript)
            this.Callback.Invoke(this.Context, true, args);
    } catch(Exception e) {
        Debug.WriteLine(e.Message);
    }
}


This method works for a while. But when the SPA changes some state, an exception is thrown:
Code: C#
Invoking function '' failed because object is invalid

This happens when a user signs in or out, even though the page has not been reloaded. The function and object sent to .NET is still accessible on the JS side.

The way I interpret this is that the pointer that .NET has available gets "out of sync" after a while.

Do you have any suggestions of how to fix or debug this?
Is there any other way of sending callbacks to JS?

Best regards
Anton
eo_support
Posted: Saturday, May 4, 2019 1:45:22 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,218
Hi,

This indeed is a problem. Currently to avoid the .NET side code interfering with the life time/GC mechanism of the JavaScript side, holding a reference on the .NET side does not prevent it from being destroyed on the JavaScript side. As such the reference on the .NET side works like a "weak reference" and the JavaScript side can become invalid.

The most reliable way to avoid such problem is to avoid holding JavaScript object on the .NET side. You can call back into .NET whenever you need to, but you would pass all necessary arguments during that call, not before in a separate call. If you must keep the object through a period of time, you can keep the object on the JavaScript side, not on the .NET side. We will also look into this to see if we can do this automatically in our library (to automatically hold a reference to a JavaScript object on the JavaScript side before passing it to .NET).

Thanks!
AAAton
Posted: Monday, May 6, 2019 10:29:27 AM
Rank: Newbie
Groups: Member

Joined: 12/12/2018
Posts: 4
Thank you for your reply.

The suggestion of holding the callback on the JS side includes some sort of named function or object that we can call from .NET, if I understand this correctly. What is the smart way of going about that? Our functions in React are not reliably named with a namespace that is accessible at a global scope. Should we try to add something to the window object?

If this could be solved by your library, that would be a relief. And a bit less of a trap for future users, I suppose.

BR
Anton
eo_support
Posted: Monday, May 6, 2019 10:48:02 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,218
Hi,

You can try to hold a reference to the function in your window object before you pass it to the .NET to prevent it from being destroyed (such as "window["your_callback"] = callback"), this is what we are looking into adding it in our library.

However please keep in mind that this will not entirely prevent the error you run into. For example, if the window object has been destroyed (such as the page has navigated to a different Url, or simply rerefreshed itself with JavaScript), then you will still receive the same error.

Thanks!
eo_support
Posted: Wednesday, May 15, 2019 3:59:52 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,218
Hi,

We have posted a new build that automatically keeps the object on the JavaScript side. If you have not already implemented the same logic in your code you can download the latest build from our download page and see if it resolves the original issue for you.

Thanks!


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.