Welcome Guest Search | Active Topics | Sign In | Register

Exception after executing .NET function from a JSExtInvoke Options
PhilipT
Posted: Tuesday, May 6, 2014 4:27:05 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
Hi,

I downloaded the latest EO.Total version and started to test and explore EO WebBrowser again.

In this EO.WebBrowser 3.0.54 version, when javascript executes the EO.extInvoke(function, params), the C# app picks up the JSExtInvoke event. Either it specifically call a C# function like A.Exit("Completed") or using MethodInfo to invoke the A's Exit function, there's always an exception. Take note that the Exit() function will fire an event too within the host application. Have not tried calling a C# function that doesn't require to fire an event.

I still have the old version of EO.WebBrowser 3.0.39 and running the same piece of code, it is not giving me any issues at all. I can always go to html and back to host app again and again without any problems at all.

Is this a known issue?

Thanks
Philip
eo_support
Posted: Tuesday, May 6, 2014 10:20:48 AM
Rank: Administration
Groups: Administration

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

There was an issue with JSExtInvoke EO.WebBrowser.dll 3.0.55, which we have updated to 3.0.56 this morning. However we are not aware of any issue with 3.0.54. But in any case you can update to 3.0.56 and see if the problem still occurs.

The most common scenario that can make extInvoke to fail is JavaScript re-entry. JavaScript engine can not be re-entered. However the ability to call into .NET code from JavaScript code makes it possible for you to call JavaScript code again from your .NET side code. In this case the JavaScript call from your .NET side code will fail because it would cause re-entry for the JavaScript engine.

Thanks!
PhilipT
Posted: Tuesday, May 6, 2014 11:08:19 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
I just tried 3.0.56 and same result. Reverting back to 3.0.39 does not have the problem.

With regards to javascript re-entry, it looks like this is a show-stopper to me. Our application requires the UI and flow to be in html/js so there will be definitely a lot of call backs in between the host app and html/js. I encountered the problem you explained about javascript re-entry but the same html/js using IE as the engine does not pose a problem to us.

Is there any solution for me? If this is by design, i'm afraid it leaves me no choice but to stick to .NET WebBrowser control :(

eo_support
Posted: Tuesday, May 6, 2014 11:23:54 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,080
Hum...that's interesting. The reason that JavaScript engine can not be re-entered has to do with the design of the JavaScript language. It should not have anything to do with the browser. For example, if you have the following JavaScript code:

Code: JavaScript
var x = 1;
alert("hi");


Then the JavaScript language guarantees that variable x will still have value 1 by the time alert("hi") returns, this means that it is not allowed for function alert to call either directly or indirectly to any other JavaScript code. If this were allowed, then it would be possible for that JavaScript code to alter variable x's value, which would break the previous rule that x will still have value 1 by the time alert returns.

In our case, alert can call into .NET code. So if you have the following call chain:

alert -> your .NET code -> someOtherJSFunction

The we will fail someOtherJSFunction on purpose in order to guarantee that you won't get a chance to modify variable x. So it's not a technical limitation that the engine can not be re-entered. It is specifically designed this way on purpose.

Hope this makes sense to you.

Thanks!
PhilipT
Posted: Tuesday, May 6, 2014 12:43:48 PM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
Ok, so based on your explanation, i should also get the same javascript re-entered issue even when using .NET WebBrowser Control since it has nothing to do with the browser.

I wrote a simple program where html/js calls Alert(), then straight call to C# function then C# automatically calls a js function in .NET WebBrowser, it went well. No js re-entered issue.

A similar program with WebView, same test but with javascript re-enter problem. The thing that puzzles me is, before the code reaches the InvokeFunction, the re-enter exception already happened at GetDOMWindow().

JSObject jsObj = m_WebView.GetDOMWindow();
jsObj.InvokeFunction(functionName, parameters);

So if truly it's the Javascript engine cannot be re-entered due to design of Javascript language, shouldn't i see the exception after InvokeFunction is called? Or are you saying that the Javascript engine for Chrome behaves differently from IE's?

Cheers...
eo_support
Posted: Tuesday, May 6, 2014 5:42:09 PM
Rank: Administration
Groups: Administration

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

That's a very interesting observation. IE's implementation will definitely cause the unexpected result of variable x being modified during alert, this is something we think is wrong but we will investigate further to see what we can find. It could be that our understanding is wrong. In that case we will remove the purposely set up blocks to allow re-entering if this proves to work fine with Chrome's script engine.

As to GetDOMWindow, this has to do with our internal implementation. Internally GetDOMWindow calls EvalScript. This can be optimized as calling the underlying DOM object directly. Since in the current implementation it uses EvalScript, it does raise the re-entering exception. After we optimize this part it should no longer be an issue.

Thanks!

PhilipT
Posted: Tuesday, May 6, 2014 11:29:36 PM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
Hi,

Do let me know your team's findings. I'm still keeping my fingers crossed that our application can have an option to use .NET WebBrowser and WebView.

Thanks a lot!
eo_support
Posted: Sunday, May 11, 2014 4:05:55 AM
Rank: Administration
Groups: Administration

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

We have posted a new build that enabled re-entering on some cases -- specifically re-entering is allowed from within custom dialog handler or JSExtInvoke handler. As such it is possible for you to have the following call flow just as an example:

1. .NET side calls WebView.EvalScript("someExtensionFunction('foo');");
2. This calls into the JavaScript engine, assume "someExtensionFunction" is a function implemented on the .NET side, this calls back to the WebView's JSExtInvoke handler, or the handler for that function if the function was registered with RegisterJSExtensionFunction;
3. Inside the handler, the code calls WebView.EvalScript("alert('bar');");
4. This calls into the JavaScript engine again, and triggers the WebView's JSDialog event;
5. Inside the JSDialog event's event handler, the code calls WebView.EvalScript("document.URL") to get the current Url;

Here the JavaScript engine is re-entered twice at step 3 and step 5. Our test did not reveal any problem with Chrome's JavaScript engine for such cases.

The EO.WebBrowser.dll version for this build is 3.0.59.0. Please take a look and let us know how it goes.

Thanks!

PhilipT
Posted: Sunday, May 11, 2014 8:16:50 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
Hi eo,

I just tested and works perfectly. Thank you very much for making this work.

Care to explain the "on some cases" this re-enter can occur? So far, using my simple app, i have done one-way calls (JS -> NET or NET -> JS) and round-trip calls (JS -> NET -> JS and NET -> JS -> NET).

Thanks
Philip
eo_support
Posted: Sunday, May 11, 2014 10:43:46 AM
Rank: Administration
Groups: Administration

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

EvalScript is still purposely blocked in a few other event handlers. For example, one of such event is BeforeNavigate. Consider the following sequence:

1. Your code call EvalScript("window.location.href=new_url;");
2. This triggers BeforeNavigate and calls back to the .NET side;
3. If you call EvalScript again inside the BeforeNavigate handler, you will receive an error (This is the same error as the "re-entry" error you had before but we now use a different error message);

The reason that is still blocked is because we have not fully tested all scenarios/code paths for these cases yet. In the above case. Step 1 actually does not wait until the new page is loaded, so by the time step 2 is called, step 1 may or may not have finished, which raises potential race conditions if we were to allow step 3 to proceed. This is something that has not been fully tested. Consider the fact that BeforeNavigate is mainly for user to determine whether the navigation should proceed, we think it might not be a huge restriction to block EvalScript inside this handler. As such the block inside this handler remains.

Thanks!
PhilipT
Posted: Thursday, June 23, 2016 4:30:51 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
Hi Eo,

I've just downloaded EO WebBrowser 16.1.17.0 and i got this exception below which i highlighted back in 2014.

Exception:
EO.WebBrowser.JSInvokeException: Invoking function 'eventArrived' failed because It is not safe to run JavaScript code at this moment. This can occur if you are inside event handlers of certain WebView events. In that case please check CanEvalScript property before calling EvalScript.

I always used a simple test program to test the round-trip calls between .NET and JS and even this version passed but when i started testing with our company's product which is event-driven, i got this exception.

The last version that worked perfectly with our company's product was 15.3.78.0 (even way back to 3.0.86/3.0.59 see the history of this topic). I really hope this is just a bug that can be fixed at your end and not us adjusting our code to the new EO version. EO WebBrowser has become a crucial component in our Web ATM projects and seriously hoping that same behavior to 15.3.78.0 can be implemented back.

Regards
Philip
eo_support
Posted: Thursday, June 23, 2016 9:17:12 AM
Rank: Administration
Groups: Administration

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

The recommended way to run JavaScript is to use QueueScriptCall. EvalScript is synchronous and convenient but there is a race condition that occurs and cause value of CanEvalScript to change from true to false right after you checked the value and before you call EvalScript. So it is not a reliable way. QueueScriptCall resolves this issue by waiting for it become safe to evaluate script code and then run the code and calls a callback you provided after it is done. So it is asynchronous but reliable.

Thanks!
PhilipT
Posted: Thursday, June 23, 2016 9:47:13 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
HI eo,

This is how we call javascript function from .NET,

private void InvokeScriptInternal(string sFunction, object[] parameters)
{
if (webViewObject != null)
{
JSObject jsObj = webViewObject.GetDOMWindow();
jsObj.InvokeFunction(sFunction, parameters);
}
}

InvokeScriptInternal("sendArray", new object[] { "John", "Joe", "Doe", 25 });

I am not using EvalScript method at all. Maybe the InvokeFunction internally is calling it. If the recommended way should be QueueScriptCall, can you show me a sample on how to call javascript function like the sample above? I could not find a sample from the help file.

Regards
Philip

PhilipT
Posted: Thursday, June 23, 2016 10:20:12 AM
Rank: Advanced Member
Groups: Member

Joined: 2/15/2014
Posts: 52
eo_support wrote:
Hi,

We have posted a new build that enabled re-entering on some cases -- specifically re-entering is allowed from within custom dialog handler or JSExtInvoke handler. As such it is possible for you to have the following call flow just as an example:

1. .NET side calls WebView.EvalScript("someExtensionFunction('foo');");
2. This calls into the JavaScript engine, assume "someExtensionFunction" is a function implemented on the .NET side, this calls back to the WebView's JSExtInvoke handler, or the handler for that function if the function was registered with RegisterJSExtensionFunction;
3. Inside the handler, the code calls WebView.EvalScript("alert('bar');");
4. This calls into the JavaScript engine again, and triggers the WebView's JSDialog event;
5. Inside the JSDialog event's event handler, the code calls WebView.EvalScript("document.URL") to get the current Url;

Here the JavaScript engine is re-entered twice at step 3 and step 5. Our test did not reveal any problem with Chrome's JavaScript engine for such cases.

The EO.WebBrowser.dll version for this build is 3.0.59.0. Please take a look and let us know how it goes.

Thanks!



Just to highlight what we have discussed 2 years ago and EO has acknowledge that javascript re-entry should be ok except for the following sequence, as also explained:

EvalScript is still purposely blocked in a few other event handlers. For example, one of such event is BeforeNavigate. Consider the following sequence:

1. Your code call EvalScript("window.location.href=new_url;");
2. This triggers BeforeNavigate and calls back to the .NET side;
3. If you call EvalScript again inside the BeforeNavigate handler, you will receive an error (This is the same error as the "re-entry" error you had before but we now use a different error message);
eo_support
Posted: Thursday, June 23, 2016 11:14:27 PM
Rank: Administration
Groups: Administration

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

InvokeFunction uses EvalScript internally. Script re-entry issue is a delicate issue and it can change from version to version. So the best way is to avoid it all together, and that's where QueueScriptCall comes into play. You can try to change it to something like this:

Code: JavaScript
var fx = window[fxName];
fx.call(window, args);


Once you convert it to that form, you can use QueueScriptCall to avoid the re-entering issue.

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.