Project

General

Profile

Bug #7040

Generated javascript can execute out-of-sequence due to a timing issue with require()

Added by Bruce Toll over 3 years ago. Updated over 3 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
05/11/2019
Due date:
% Done:

0%

Estimated time:

Description

With github wt 4.0.5-31-ga05a7c5d, applications that load javascript with require() can encounter a timing issue where generated javascript is executed out-of-sequence, leading to client-side javascript errors or other problems. I originally encountered this issue with a widgetset application that displays two widgets: a WTableView and a custom widget that uses leaflet.js.

The attached test program is more minimal, but somewhat contrived. While the original issue occasionally occurred with an unmodified version of Wt, a small change would made it occur consistently and that change is also needed to reliably reproduce the issue using the attached test program. The required change is at line 3191 in Wt.js: increase the timeout from 50ms to 500ms or higher, e.g.:

setTimeout(function() { handleResponse(status, msg, timer); }, 500);

With that change, the test program should generate client-side javascript errors when configured to use web-sockets and accessed with Chromium.

The issue seems related to how javascript libraries are loaded:

1. While a library is being loaded a waitingForJavaScript flag is set.

  1. While waitingForJavaScript is set, the processing of response messages from the server are deferred for 50 ms.
  2. When a javascript library has completed loading, the waitingForJavaScript flag is cleared and associated code that depends on it is executed.
  3. Finally, any pending updates are sent to the server.

The issue appears to be that updates from step 4 can make it to the server and get a response back to the client's handleResponse before the timer in step 2 expires. Thus, the latter response gets handled by the client before the earlier deferred response.

In addition to the test program, two patches are attached:

0001-Fix-Wt.js-waitingForJavaScript-sequence-issue.patch --- This is a small patch that replaces the setTimeout mechanism with a queue. It has been minimally tested, but would benefit from additional review and testing. There are additional notes on the patch.

0002-Additional-waitingForJavaScript-debugging-code.patch --- This contains additional console logging and notes on testing. In conjunction with the test program, the logging can provide insight into the queue behavior before and after the patch.

If I can provide any further information, or if you have trouble reproducing, please let me know. The issue appears to be both browser and timing sensitive. It probably only occurs with web-sockets enabled.


Files

#1

Updated by Bruce Toll over 3 years ago

Additional notes:

  1. The 500ms setTimeout value referenced above may not be sufficient to drive the issue, especially if built with DEBUG logging and running with full logging. In any case, if you don't get a reliable failure at 500ms, you can try increasing the timeout value.
  2. The use of "naked" debug in wt_config.xml with chromium will provide more information on the failing javascript so that you can associate the missing DOM element with the server-side log.
  3. To get the browser debugger to stop at the point of failure, I found the following patch to DomElement.C helpful:

<!-- -->

diff --git a/src/web/DomElement.C b/src/web/DomElement.C
index 59a56af5..6cd80023 100644
--- a/src/web/DomElement.C
+++ b/src/web/DomElement.C
@@ -1129,8 +1129,10 @@ std::string DomElement::createVar() const

 void DomElement::declare(EscapeOStream& out) const
 {
-  if (var_.empty())
+  if (var_.empty()) {
     out << "var " << createVar() << "=" WT_CLASS ".$('" << id_ << "');\n";
+    out << "if (" << var_ << " === null) debugger;\n";
+  }
 }

Also available in: Atom PDF