Project

General

Profile

Bug #2125

Wt internal error using WDatePicker (and others)

Added by Jesse Pepper almost 9 years ago. Updated almost 9 years ago.

Status:
Feedback
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
08/21/2013
Due date:
% Done:

0%

Estimated time:

Description

Hi There,

I'm getting the following error popping up in a dialog quite often:

"Wt internal error: TypeError: Cannot set property 'className' of null, code: undefined, description: undefined."

The error seems to occur when, for example, a date picker is used, and it is showing the calendar popup, and while the calendar is up, the WDatePicker instance is destroyed.

Sorry, no test code at the moment, but just from the description, does it sound like this kind of thing might be a problem?

Any ideas?


Files

Wt Error.png (21.8 KB) Wt Error.png Error dialog Jesse Pepper, 08/24/2013 10:47 PM
Capture.PNG (41.2 KB) Capture.PNG Anonymous, 09/09/2013 10:28 AM
#1

Updated by Jesse Pepper almost 9 years ago

Note, I am using version 3.3.0-rc3. The problem doesn't appear to be browser specific (tested with IE and chrome).

#2

Updated by Jesse Pepper almost 9 years ago

The message in IE is slightly different: "Wt internal error: Error: Could not complete the operation due to error 80020101., code: undefined, description: Could not complete the operation due to error 80020101."

#3

Updated by Wim Dumon almost 9 years ago

  • Status changed from New to Feedback

Hello Jesse,

could you try our newly released 3.3.1rc1 and report back if you still see the problem? Many bugs have been fixed since 3.3.0-rc3.

Thank you,

Wim.

#4

Updated by Jesse Pepper almost 9 years ago

Hi Wim, just finished getting it running with the 3.3.1-rc1 and the same problem is still there. I can see one scenario where it used to happen and now is not, but I can still force it to happen easily. I'm not sure but it could be perhaps that when the calendar dialog is obscured / partially visible, and then a button is clicked that will result in the WDatePicker being destroyed, it still happens.

This is a bit of a showstopper for us at the moment, and we are intending to do a trial of the product in the next week, so any advice would be much appreciated.

Thanks,

Jesse

#5

Updated by Wim Dumon almost 9 years ago

Can you set this option in wt_config.xml, run with the JS debugger enabled, and let me know the source of the error (+ if possible a stack trace)?

        <!-- Javascript debug options

             Values:
             - true: JavaScript errors are not caught but the browser
                     built-in debug options are used
             - stack: JavaScript errors are caught but also a stack trace
                      is printed, useful for diagnosing a problem in production
             - false: JavaScript errors are caught and a simple error message
                      is printed to indicate that something is terribly wrong
          -->
        <debug>true</debug>

Wim.

#6

Updated by Anonymous almost 9 years ago

Hi Wim,

I've been looking into this with Jesse today and have some information that may help in understanding the problem. I've tried to reproduce the problem with an isolated test case with no luck so far, but it's difficult to know exactly what's happening as this is all tied up with various frameworks of ours.

The problem seems to occur when the calendar popup of the WDatePicker is shown at the point that the WDatePicker is destroyed. In our code we tend to delay the deletion of widgets as they may hold state that asynchronous tasks refer to. Instead we call removeWidget() on the parent WContainerWidget to remove widgets from the gui and then queue the widget to be deleted once it is safe to do so. This in itself does not seem to be causing the problem as in my test case it all worked fine - though there was one oddity; since the popup calendar is destroyed in the WDatePicker's destructor, it stays on screen until the WDatePicker is destroyed. I think this is innocuous, but maybe it's a clue as to the problem we're seeing.

In our framework we strictly separate phases of mutating the application's models in response to user events (eg, setting the date in some model when the user selects a date in the popped up calendar) and recalculating the state of views. Roughly what happens is along these lines:

1. We receive an event/signal, eg, the user selecting a date in the popup calendar

  1. In the event handler we mutate out data model
  2. The data model signals any views that the model has changed
  3. Views merely record that they are dirty - that is, we do not push changes into the GUI while we are handling events.
  4. Some time later the GUI needs to be updated. Currently we do this:
  • If any widgets are marked as dirty, we call Wt::WContainerWidget::scheduleRender()
  • At the top of the widget tree we have a special container which in it's render() method "cleans" dirty widgets before calling the default render() implementation.
    1. Cleaning widgets may involve calling removeWidget() as noted earlier, creating new widgets and setting the state of existing widgets.

Interestingly, calling removeWidget() seems necessary in some cases as I found out in my test case; if a WDatePicker tries to delete itself in response to the user selecting a date then a crash results!

I have some ideas for work arounds and will try these when I get a chance, but any comments you have on the above would be appreciated.

Cheers,

Dan

#7

Updated by Jesse Pepper almost 9 years ago

Hi Wim,

In Chrome, I get this in the console, with the debug option enabled:

Uncaught TypeError: Cannot read property 'style' of null

(anonymous function)

(anonymous function)

ca ?wtd=0luVxQcfRnf6Rlw1&sid=--1908062687&htmlHistory=true&deployPath=%2F&request=script&rand=1878269187:212

I ?wtd=0luVxQcfRnf6Rlw1&sid=--1908062687&htmlHistory=true&deployPath=%2F&request=script&rand=1878269187:212

c.onmessage ?wtd=0luVxQcfRnf6Rlw1&sid=--1908062687&htmlHistory=true&deployPath=%2F&request=script&rand=1878269187:213

I hope that helps.

Regards,

Jesse

#8

Updated by Wim Dumon almost 9 years ago

Hello Jesse,

I would have to see some code in that stack frame, and probably also in the stack frames below that. Where does that null originate from?

BR,

Wim.

#9

Updated by Koen Deforche almost 9 years ago

Hey Daniel,

We really need something to work with to solve this (a test case), but perhaps some hints on how to help you get one.

The problem seems to occur when the calendar popup of the WDatePicker is shown at the point that the WDatePicker is destroyed. In our code we tend to delay the deletion of widgets as they may hold state that asynchronous tasks refer to. Instead we call removeWidget() on the parent WContainerWidget to remove widgets from the gui and then queue the widget to be deleted once it is safe to do so. This in itself does not seem to be causing the problem as in my test case it all worked fine - though there was one oddity; since the popup calendar is destroyed in the WDatePicker's destructor, it stays on screen until the WDatePicker is destroyed. I think this is innocuous, but maybe it's a clue as to the problem we're seeing.

So that does mean that you only actually delete widgets from during the render phase?

  1. Some time later the GUI needs to be updated. Currently we do this:
    * If any widgets are marked as dirty, we call Wt::WContainerWidget::scheduleRender()

I don't understand this: this is only for a widget that is a container? You specialized all the widget's render methods?

* At the top of the widget tree we have a special container which in it's render() method "cleans" dirty widgets before calling the default render() implementation.

So there's only one special render() implementation?

There is one thing to consider with doing things within the render() implementation: it should only touch widgets that are contained by it. Widgets like date pickers (and other WPopupWidget's) root themselves in a top container. So perhaps this is where the problem lies.

Regards,

koen

#10

Updated by Anonymous almost 9 years ago

Hi Koen,

I'm spread really thin at the moment and not getting time to look into this much, so I've not made headway on a test case. I'll try to find some time to work on this soon.

So that does mean that you only actually delete widgets from during the render phase?

Widgets may be removed from their parent during the render phase, but deleting them happens some time later. In the implementation that showed up this problem, deleting of widgets was being done when handling the next event for a session. I have since fiddled with the timing of the deletion of widgets and have found that deleting widgets more eagerly, specifically during the render call, fixed some of our problems.

We need to be careful with what "during the render phase" means. What I really want is a callback that signals the end of event processing and the start of the render phase. To emulate this we hijack the render callback of our root container and do all our cleaning during that call before calling the base class render method. The cleaning will be limited to widgets descended from that root container (though, you note special the special case of popups).

I don't understand this: this is only for a widget that is a container? You specialized all the widget's render methods?

Sorry, I should have been more clear. If any widgets become dirty, we call Wt::WContainerWidget::scheduleRender() on our special root container, ensuring that we get a render call during which we can clean our widgets. Only the root node is special with regard to the render method.

So there's only one special render() implementation?

That is correct.

There is one thing to consider with doing things within the render() implementation: it should

only touch widgets that are contained by it. Widgets like date pickers (and other WPopupWidget's)

root themselves in a top container. So perhaps this is where the problem lies.

Yeah, this sort of thing could be the source of the problem. However, I've seen the same javascript error result when no popups have been involved (or at least it seems that no popup is involved).

I used to perform cleaning even later, using a message posted to the WServer. This seems more reliable, however it means that every single change to the widget tree uses server push to propagate changes to the client. It seems far better to be able to use the http response for the request that contained the events if possible. Perhaps this is less of a concern when web sockets are used?

Cheers,

Dan

#11

Updated by Anonymous almost 9 years ago

Hi Koen and Wim,

I'm pretty convinced that the source of the error we are seeing is caused by the render() method of the root of our widget tree causing changes to widgets that are not descended from that widget. Specifically popups that add themselves to the domRoot().

Is there any sort of hook that you can think of that gives the application a look-in between event handling and rendering phases? I had a bit of a hunt through the WebSession and WApplication implementation today and nothing jumped out. In the interim I've fallen back to my other method of posting to the server.

I have a related problem, which I'll report here, where the same javascropt error is produced. From what I can tell, the scenario is as follows:

1. A WPushButton is created as the child of a WContainer (the container uses a layout to position its children).

  1. Some state in our application changes, causing both the button and the container to become dirty; the button wants to update it's label, but the container wants to create a new set of children.
  2. Given our algorithm, the button actually gets cleaned first, so the label gets updated. The container then gets cleaned, and so the button is removed from the container (note, it is removed, not deleted).
  3. In the browser we get a javascript error. See attached error with stack trace.

Can you see any problem with the above scenario? Is it valid to make changes to a widget and then remove it from the widget tree inside a callback posted to the server? There may be some sort of order dependence here as I have cases where it causes the error and others where it seems to be just fine. Is it related to the order in which changed to the DOM are applied on the client?

Cheers,

Dan

#12

Updated by Anonymous almost 9 years ago

Sorry, a couple of things I didn't mention in my previous post.

1) If you ignore the error, all the widgets on screen seem to be correct.

2) Even if the button is deleted (not just removed), the error still occurs.

Hope that helps a little.

Cheers,

Dan

#13

Updated by Anonymous almost 9 years ago

This last reported problem is a misuse of Wt on our part, so please ignore it. I found that we are removing the widget from the container, but it is not removed from the layout. Although I've not had a chance to correct this, I am sure this is the source of the problem.

Cheers,

Dan

Also available in: Atom PDF