Author Topic: [PJSR] Question on assigning controls to Sizer only (to Juan)  (Read 5042 times)

Offline bitli

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 513
The question is really to Juan:
Quoting http://pixinsight.com/forum/index.php?topic=2584.msg17440#msg17440 of Nov 2010:
 
Quote
Try to avoid leaving potentially unrooted child controls in a dialog's constructor.
So we should use
Code: [Select]
this.foo = new Label( this );instead of, say:
Code: [Select]
var label = new Label(this);
this.sizer.add(label);
Is this still true in this specific case? Especially if we add the Control to a Sizer in the same block, is there a chance that it is garbage collected when it is only referenced by the Sizer?
The reason is that the need to directly assign the control make it slightly more inconvenient to create method that add a couple of controls to a container (for example a sizer with a label and a control). If this is still required, so be it, but as I write some example scrripts, I would not like to propagate a limitation if it is not appropriate anymore.
-- bitli



Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: [PJSR] Question on assigning controls to Sizer only (to Juan)
« Reply #1 on: 2013 February 19 00:08:06 »
Quote
Is this still true in this specific case? Especially if we add the Control to a Sizer in the same block, is there a chance that it is garbage collected when it is only referenced by the Sizer?

Yes. Note that the internal mechanism by which a control is managed by a Sizer object is completely unknown to the JavaScript engine. Adding a control or a Sizer to a Sizer does not create a dependency from the JavaScript side. Although unlikely, your control can get garbage collected asynchronously, often with catastrophic results.

So the only way to ensure that a child control cannot be destroyed unexpectedly due to garbage collection, is to make it a property of an existing control (usually its parent control, although not necessarily). Besides Dialog, which is (for now) the only top-level control available in PJSR, no unrooted control should exist in a PixInsight script.

So this is safe and correct:

Code: [Select]
function MyDialog( parent )
{
   // ...
   this.foo = new Label( this );
   // ...
}

This is dangerous:

Code: [Select]
function MyDialog( parent )
{
   // ...
   var foo = new Label( this );
   // ...
   this.foo = foo;
   // ...
}

And this is even more dangerous:

Code: [Select]
function MyDialog( parent )
{
   // ...
   var foo = new Label( this );
   // ...
   this.sizer.add( foo );
   // ...
}
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline bitli

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 513
Re: [PJSR] Question on assigning controls to Sizer only (to Juan)
« Reply #2 on: 2013 February 19 04:56:05 »
Thanks.  I need to check my scripts quickly (I used to avoid exposing stuff as properties unless they are needed). This will be done as soon as possible, but probably in 2 days or so.
I will try to rephrase the rule more generally to see if I understood the rules governing 'wrapper objects' and 'finalization/gc' in PJSR and post it for your review.
-- bitl

Offline bitli

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 513
Re: [PJSR] Question on assigning controls to Sizer only (to Juan)
« Reply #3 on: 2013 February 20 12:44:04 »
To be on the safe side:
Is there any similar issue with TreeBoxNode?  Creating them seems to add the to the TreeBox, do I have to keep a parallel list too to avoid GC?
-- bitli

Offline bitli

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 513
Re: [PJSR] Question on assigning controls to Sizer only (to Juan)
« Reply #4 on: 2013 February 21 23:48:34 »
Sorry to bug you on this again.
First a question:
Why would
Code: [Select]
function MyDialog( parent )
{
   // ...
   var foo = new Label( this );
   // ...
   this.foo = foo;
   // ...
}
be dangerous?
My understanding is that the Control (Label) Javascript proxy will delete the Label when it is garbage collected. The label is referenced by a local variable in the method, and surely the local variables are not garbage collected before we exit of the scope (or at lease before they are not referenceable anymore)? I am asking this because it is often boring and error prone to add 'this' everywhere (or not quite right everywhere) and would be simpler if we could just add the control to the sizer before its variable can be out of scope.

Then, after making the required changes on one script and working on another, I found this issue pretty annoying, especially if you do some dynamic controls or control tables. It is easy to forget, and impossible to test. I have looked at SpideerMonkey and it is true that the GC and its documentation is not very clear. But considering that the only (or at least usual and correct) way to add a control is via the Javascript proxy of a Sizer, via the add/remove, could the Sizer proxy not have a private field to whish it would add/remove controls when they are added/removed from the Sizer ? Naturally this only works if the control proxy keeps track of the Sizer proxy and does not generate a new one when the property is referenced. This may not cover all the cases, especially not if Javascript and native code is ever mixed, but would avoid maintaining a parallel hierarchy manually.

Alternatively I could make sub classes of the controls and Sizer to provide this functionality, but I am not sure this would work as the PJSR is pretty picky on the class herarchy of controls. Besides, I am lazy.

-- bitli