[Laszlo-user] [Laszlo-dev] API change proposal: <node>/destroy behavior, when destroying child nodes recursively
P T Withington
ptw at pobox.com
Thu Jan 29 06:00:19 PST 2009
On 2009-01-27, at 14:52EST, André Bargull wrote:
> On 1/27/2009 4:47 PM, P T Withington wrote:
>> On 2009-01-27, at 09:46EST, André Bargull wrote:
>>>
>>> On 1/27/2009 1:03 AM, P T Withington wrote:
>>>> On 2009-01-26, at 18:24EST, André Bargull wrote:
>>>>> Oh wait, you just said nothing in the LFC depends on the current
>>>>> way things work. I really believed in you,
>>>> But wait, I said:
>>>> "where a child node _needs_ to access it's parent when the parent
>>>> is in the process of being deleted"
>>>> so, there may be cases where it _does_ access the parent, but
>>>> does it _need_ to? I don't think it does. So it is just a matter
>>>> of fixing those cases to be careful.
>>>
>>> How do you plan to find those cases?
>> One way would be to set parent to null and then fix the bugs it
>> reveals.
>
> It'd be great to have JS2 getters in this case. So you can generate
> a debugger warning in one release and by that give people the chance
> to update their sources. And in a next release, you'd apply the real
> proposed change. That way user applications continue to work.
> Like:
> ---
> private var _parent:LzNode;
> public function get parent () :LzNode {
> if ($debug) {
> if (_parent.__LZdeleted) {
> Debug.warn("danger");
> }
> }
> // return parent but give a warning when parent is already destroyed
> return this._parent;
> }
> ---
>>
If wishes were horses...
Given that we don't have setters, what do you propose?
>>> For example what is going to happen for constraints? The example
>>> [2] isn't a real-life example (it makes no sense to do anything
>>> like that), but through replication [1] and other means, you can
>>> end up destroying the parent-node and then it's really difficult
>>> to find the source of possible runtime errors.
>> This is exactly what led me down this path. I was looking at
>> replication in nav.lzx and realized that it was making hundreds of
>> useless operations because as each child was destroyed, it told the
>> parent to update its layout, which caused the parent to adjust the
>> position of each child (even though that child would be destroyed
>> soon).
>
> Adding the same if-condition to "__LZresolveReferences" as in
> "__LZapplyArgs" ('bail if deleted'), presumedly helps to reduce some
> useless operations when applying constraints to destroyed nodes..
Yes, but this is really just another band-aid for a problem that I am
trying to fix at the source.
>> Doesn't this just indicate a bug in the interaction of replication
>> and the focus manager? My take is that you are updating your
>> dataset, so the replicator destroys and re-allocates nodes to
>> represent the updated dataset, but the focusmanager is still
>> hanging on to the destroyed node.
>
> When the new data-node is added, replication just starts to run.
> It's more about pooling, but see below.
>
>
>> Either the focus manager needs to store its state in terms of "dom
>> position" (i.e., a path to the node that has focus, rather than a
>> reference to the actual node), or the replication manager has to
>> cooperate with the focus manager to tell it when it has replaced
>> the node that has focus.
>> Why does it work for lazy replication? Because the lazy replicator
>> is much more careful not to destroy a node that maps to a data
>> element that is still in the range when it is updated -- it leaves
>> those nodes in place. This would be one way to fix the bug for
>> normal replication, and it would presumably make it more efficient
>> too!
>
> Almost right: in normal replication (without pooling!), the initial
> node is destroyed. But in lazy replication, pooling is automatically
> enabled, so the initial node is not destroyed and therefore no
> runtime exception is generated.
That's what I was trying to say.
> And the bug is not caused by the replication-manager, it's a bug in
> LzView. The view must check in its destroy method the current focus
> and if necessary clear focus.
This really depends on your point of view. I see it as a bug in the
focus manager, or at least a bug by the person who wrote the focus
manager, which was added after views but failed to consider that views
are allowed to be destroyed.
> (I just used that replication example because I know how replication
> works, so it's easily possible for me to force runtime exceptions
> under certain conditions.)
I am sure there are lots of ways you can demonstrate that my proposal
will cause a runtime exception. My claim is that for each one you
demonstrate, when we dig into it, we will find that there is a design
flaw at the root of it that at best will cause a memory leak, or worst
will cause the program to not behave as expected.
My premise is that when a node is destroyed, the intent is that the
node is disconnected from the LZX 'DOM-tree', hence any code that is
trying to navigate the DOM starting from that destroyed node is
erroneous. The fact that _currently_ we leave the parent links
pointing to what used to be the parent of the node in the tree is
broken, because that node is no longer a child of the parent.
More information about the Laszlo-user
mailing list