TTMSFNCWebBrowser script queue deadlocks permanently when one ExecuteScript completion is lost (WebView2)

Component: TMS FNC Maps / TMS FNC Core, VCL, Delphi 13 (32-bit), WebView2/Edge on Windows.

Problem: TTMSFNCCustomWebBrowser.ExecuteJavaScript (non-immediate) serializes scripts through FScriptList: the next script is only submitted from DoScriptHandled, which is invoked as the completion callback of the previous ICoreWebView2.ExecuteScript call (TCoreWebView2ExecuteScriptCompletedHandler.Invoke in VCL.TMSFNCWebBrowser.Win.pas). If a single completion never arrives, the chain is broken permanently: every later non-immediate script is appended to FScriptList but never submitted. There is no timeout or recovery, and FScriptList is not cleared on Navigate/Reload/ReInitialize — only the destructor frees it — so the control never recovers until the application restarts.

The same pattern exists in TTMSFNCCustomMaps.UpdateMarkers: FAwaitingDoUpdateMarkers is set before ExecuteJavaScript(GETMARKERARRAYVAR, DoUpdateMarkers, True) and only cleared in DoUpdateMarkers; a lost completion means markers are never updated again (the guard is only reset in the constructor).

How we hit it: our application occasionally shows a modal dialog (from a TThread.Queue callback) while the user is moving the mouse over the map, so hover scripts and their completions are in flight. Occasionally WebView2 then never delivers the pending ExecuteScript completion (apparently lost while the modal message loop runs during a WebView2 callback). Afterwards all queued scripts and marker updates stop working while immediate scripts still work. It is hard to reproduce on demand but recurs in production.

Suggested fix: record a tick when the head script of FScriptList is submitted; when ExecuteJavaScript queues a new script and the head is older than a few seconds, call DoScriptHandled(nil) to restart the chain. Also check the HRESULT of ICoreWebView2.ExecuteScript in TTMSFNCWinWebBrowser.ExecuteJavascript and invoke the callbacks on failure, and add a similar timeout to the FAwaitingDoUpdateMarkers guard. Could you add such self-healing?

We'll investigate this here as soon as possible.

Thanks for the detailed analysis. It matched what we found in the code.

We’ve fixed this in TMS FNC Core 4.5.0.7 (TTMSFNCWebBrowser 1.3.4.3):

  • Recovery from a stuck queue: the queue now records when its current script was sent. If a new script is queued and that script still hasn’t completed after 5 seconds, the queue restarts. No queued script is skipped.
  • Failed ExecuteScript calls: the HRESULT of ICoreWebView2.ExecuteScript is now checked. If the call fails, the completion callbacks are called right away, because WebView2 never calls them in that case.
  • Exceptions in a completion handler: the queue now moves on even when your completion event raises an exception. Before, that also stopped the queue for good.

The FAwaitingDoUpdateMarkers guard in TTMSFNCCustomMaps.UpdateMarkers is part of TMS FNC Maps. It will get a similar timeout in a separate update. With the Core fix, marker updates already recover when ExecuteScript fails. A completion that WebView2 loses can still block them until the Maps update is out.