From: Garrett Smith on
kangax wrote:
> On 2/11/10 2:49 PM, Garrett Smith wrote:
>> kangax wrote:
>>> On 2/8/10 7:49 PM, Garrett Smith wrote:
>>>> I'm confuse
[...]

> Doesn't have to be a DOM object. Could be any object that has `window`
> property referencing object itself.
>

It must be an object that has attachEvent or addEventListener.

> (function(){
> var o = { };
> o.window = o;
> return (o.window == o); // true
> })();
>

That won't likely happen because the object is duck-type checked:-

if(!src.addEventListener && !src.attachEvent) {
throw TypeError(src+ " is not a compatible object.");
}

What has either attachEvent or addEventListener, plus a window property
pointing to itself?

>> why that would be the case.
>>
>> obj != obj.window
>>
>> should always be true when obj is not a window.
>
> Well, in IE `window === window` is false. Where's guarantee that `window
> == window` won't be false either?
>
AISI, window === window.window being false IE is a bug of IE. I don't
understand why that is. At best it is a "quirk" of IE.

The specification makes wide loopholes for host objects, but we do know
that global is an object, and if global === other is true, than other is
the global object (and so is an Object, by implication).

this === window in global context, and so the only way this.window !==
window could be true, is if the window object were resolved off the
variable object (which is, by design fault, a different object in IE,
going back to Eric Lippert's blog[1]).

In that case, if the window object were resolved on the variable object,
it could be a different object then that referred to by the global
object's window property, and in that case, then window == global.window
should be false.

In global context, has `window == this.window` ever been observed to be
false?

Strict equals `this.window === window` is false in IE, but that is part
of the bug I am working around.

> But then again, as it stands now, I don't see a safe way to detect
> window in cross-browser manner, and avoid chance of false positives
> (it's either duck-typing or self-referencing comparison like the one you
> mention; both can fail).
>

Maybe, but I can't think of a case where an object has attachEvent and
has a window property that is == to itself.

[...]

>>
>>
>> Function cleanUp is added if isMaybeLeak, but that is done only when
>> `get` is called.
>
> Why not avoid cleanup completely?
>

The cleanup helps older versions of IE (IE6 SP1 and earlier) remove
references. IE memory leak error got fixed in IE6 SP2 and is in in IE7.
With the fix, when a page is navigated away, the references get
cleaned up.

Another consideration not yet accounted for is events attached to
objects where an ancestor's innerHTML changes, removing the object. In
that case, the object should be purgeable, by say Event.purge(obj).

[...]

>
> Have you considered writing your own testing lib?

Yes I have considered writing a testing framework. It is a lot of work.
Even more work to rewrite all of my tests that are using YUI Test. I
suppose the rewriting of unit tests might be at least partially
alleviated by creating aliases and adapters.

As they say, if you want something done right, do it yourself. Well I
am, but it is a lot of work. It isn't exactly easy to find good
developers and even harder to find good developers who want to work for
free on somebody else's (my) project.

I have made a lot of checkins in the 8 months, so was busy with those
things, but yes, I am considering writing a unit test framework.

[1]http://blogs.msdn.com/ericlippert/archive/2005/05/04/414684.aspx
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: David Mark on
Garrett Smith wrote:
> kangax wrote:
>> On 2/11/10 2:49 PM, Garrett Smith wrote:
>>> kangax wrote:
>>>> On 2/8/10 7:49 PM, Garrett Smith wrote:
>>>>> I'm confuse
> [...]
>
>> Doesn't have to be a DOM object. Could be any object that has `window`
>> property referencing object itself.
>>
>
> It must be an object that has attachEvent or addEventListener.
>
>> (function(){
>> var o = { };
>> o.window = o;
>> return (o.window == o); // true
>> })();
>>
>
> That won't likely happen because the object is duck-type checked:-
>
> if(!src.addEventListener && !src.attachEvent) {
> throw TypeError(src+ " is not a compatible object.");
> }
>
> What has either attachEvent or addEventListener, plus a window property
> pointing to itself?
>
>>> why that would be the case.
>>>
>>> obj != obj.window
>>>
>>> should always be true when obj is not a window.
>>
>> Well, in IE `window === window` is false. Where's guarantee that
>> `window == window` won't be false either?
>>
> AISI, window === window.window being false IE is a bug of IE. I don't
> understand why that is. At best it is a "quirk" of IE.
>
> The specification makes wide loopholes for host objects, but we do know
> that global is an object, and if global === other is true, than other is
> the global object (and so is an Object, by implication).
>
> this === window in global context, and so the only way this.window !==
> window could be true, is if the window object were resolved off the
> variable object (which is, by design fault, a different object in IE,
> going back to Eric Lippert's blog[1]).
>
> In that case, if the window object were resolved on the variable object,
> it could be a different object then that referred to by the global
> object's window property, and in that case, then window == global.window
> should be false.
>
> In global context, has `window == this.window` ever been observed to be
> false?
>
> Strict equals `this.window === window` is false in IE, but that is part
> of the bug I am working around.
>
>> But then again, as it stands now, I don't see a safe way to detect
>> window in cross-browser manner, and avoid chance of false positives
>> (it's either duck-typing or self-referencing comparison like the one
>> you mention; both can fail).
>>
>
> Maybe, but I can't think of a case where an object has attachEvent and
> has a window property that is == to itself.
>
> [...]
>
>>>
>>>
>>> Function cleanUp is added if isMaybeLeak, but that is done only when
>>> `get` is called.
>>
>> Why not avoid cleanup completely?
>>
>
> The cleanup helps older versions of IE (IE6 SP1 and earlier) remove
> references. IE memory leak error got fixed in IE6 SP2 and is in in IE7.
> With the fix, when a page is navigated away, the references get cleaned
> up.
>

But that doesn't answer the question. Why not avoid that issue entirely
by not creating circular references? I have the same sort of cleanup in
mine, which I will be removing (or at least making optional) when I get
around to it, as it is superfluous. Unload listeners should be avoided
at all costs as they foul up navigation, increasing server hits and
testing user patience.
From: kangax on
On 2/11/10 11:35 PM, David Mark wrote:
> Garrett Smith wrote:
>> kangax wrote:
[...]
>>> Why not avoid cleanup completely?
>>>
>>
>> The cleanup helps older versions of IE (IE6 SP1 and earlier) remove
>> references. IE memory leak error got fixed in IE6 SP2 and is in in IE7.
>> With the fix, when a page is navigated away, the references get cleaned
>> up.
>>
>
> But that doesn't answer the question. Why not avoid that issue entirely
> by not creating circular references? I have the same sort of cleanup in
> mine, which I will be removing (or at least making optional) when I get
> around to it, as it is superfluous. Unload listeners should be avoided
> at all costs as they foul up navigation, increasing server hits and
> testing user patience.

Well, this isn't really an issue, as you would only perform cleanup in
IE (e.g. <8), and those versions of IE (at least 6 and 7, last time I
checked) don't have fast history navigation.

--
kangax
From: Garrett Smith on
kangax wrote:
> On 2/11/10 11:35 PM, David Mark wrote:
>> Garrett Smith wrote:
>>> kangax wrote:
> [...]
>>>> Why not avoid cleanup completely?
>>>>
>>>
>>> The cleanup helps older versions of IE (IE6 SP1 and earlier) remove
>>> references. IE memory leak error got fixed in IE6 SP2 and is in in IE7.
>>> With the fix, when a page is navigated away, the references get
>>> cleaned
>>> up.
>>>
>>
>> But that doesn't answer the question. Why not avoid that issue entirely
>> by not creating circular references? I have the same sort of cleanup in
>> mine, which I will be removing (or at least making optional) when I get
>> around to it, as it is superfluous. Unload listeners should be avoided
>> at all costs as they foul up navigation, increasing server hits and
>> testing user patience.
>
> Well, this isn't really an issue, as you would only perform cleanup in
> IE (e.g. <8), and those versions of IE (at least 6 and 7, last time I
> checked) don't have fast history navigation.
>
I am not doing cleanup for IE7. That is called only where cc identifies
the script engine that shipped with the same engine that IE6 shipped with.

A reference to the DOM object is saved as a property of the wrapped
function and used fixing the context in callback.call(obj, callback).
That wrapped function is only used internally.

Once that object reference is saved, it needs to be removed to break the
circular reference (because IE won't).

The function Object has a `context` property pointing to a DOM object.

fun.context --> DOM obj

When a function is attached to a DOM object using attachEvent, IE
associates that function using an internal reference, as:

DOM obj --> fun

Put those together an you get:
DOM obj --> fun --> fun.context --> DOM obj.

To break that, I use:
delete fun.context.

I believe that will break the cycle.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: David Mark on
kangax wrote:
> On 2/11/10 11:35 PM, David Mark wrote:
>> Garrett Smith wrote:
>>> kangax wrote:
> [...]
>>>> Why not avoid cleanup completely?
>>>>
>>>
>>> The cleanup helps older versions of IE (IE6 SP1 and earlier) remove
>>> references. IE memory leak error got fixed in IE6 SP2 and is in in IE7.
>>> With the fix, when a page is navigated away, the references get
>>> cleaned
>>> up.
>>>
>>
>> But that doesn't answer the question. Why not avoid that issue entirely
>> by not creating circular references? I have the same sort of cleanup in
>> mine, which I will be removing (or at least making optional) when I get
>> around to it, as it is superfluous. Unload listeners should be avoided
>> at all costs as they foul up navigation, increasing server hits and
>> testing user patience.
>
> Well, this isn't really an issue, as you would only perform cleanup in
> IE (e.g. <8), and those versions of IE (at least 6 and 7, last time I
> checked) don't have fast history navigation.
>

And how do you suggest to tell it is definitely IE < 8. I suppose you
could resort to conditional compilation plus various object inferences,
but, as you mentioned, why not avoid all of that?

Are you sure? ISTM that they do, though perhaps not in the same sense
as the other majors. Perhaps rather than preserving the DOM, it
preserves the initial state of the DOM, in which case unload listeners
won't matter. Still no reason to bother with such complications.