Peter Michaux wrote:
<snip>
Richard Cornford wrote:
<snip>
>That is precisely what happens. The anonymous function
object has an internal [[Scope]] property that refers
to the scope chain structure of the execution context
in which the function was created (as a result of the
evaluation of the function expression as part of the
assignment to - request.onreadystatechange -). That
scope chain structure includes (so must refer to) the
Activation/Variable object from the containing execution
context, and that Activation/Variable object has a
"request" property that refers to the xml http request
object.
I haven't read about the "Activation/Variable" term before.
ECMA 262 3rd Ed. Section 10.
Is that slashed because different browsers call it different
things?
It is slashed because the Activation object becomes (is used as) the
Variable object for a function's execution context. (Global execution
contexts do not need, so do not have, and Activation object but the
global object is then used as the Variable object)
Flanagan refers to this object as the "call" object ("JavaScript the
definitive guide", 5th Ed. Chapter 8, Section 8.8.2, page 142), and
briefly mentions that it is the ECMAScript "activation" object.
Unfortunately the succession of questions to this group over the years in
which readers of Flanagan have confused his "call" object with the object
providing the - this - value when a function is called demonstrates the
wisdom of using such ill defined terminology.
[snip]
>Incidentally, the fact that - request.onreadystatechange -
refers to the function object, the function object refers
to the Activation/Variable object (through its scope chain)
and the Activation/Variable object refers to the xml http
request object gives a circular chain of references and so
will provoke IE's memory leak problem.
So in a non-IE browser, what is stopping this circle of
objects to be garbage collected as a group?
That is, what is pointing to one of it's several objects?
Probably whatever mechanism links the HTTP response from the request with
the xml http request object that made the original request. Presumably
the browser must have a way of referring to the xml http request object
(directly, or more directly) so that it can do something appropriate when
the response arrives.
>The fact that the - onreadystatechange - handler does
nothing to break this circular reference actually mans
that on IE none of the objects involved will be garbage
collected until the browser shuts down. Making this yet
another unwise example form Flanagan (there is also
a missing third argument to the - open - call, which is an
issue in some xml http request object implementations, and
implies synchronous requests in others (implicit Undefined
type-converts to false), for which - onreadystatechange -
handers are unnecessary, and in some implementations they
will not be called).
I assume my goal is to break this circle and am not sure if
I have this correct.
Yes, you should explicitly break the circle else IE will not free the
memory involved until the browser closes (at least with the ActiveX
version of xml http request objects, the native version in IE 7 may not
exhibit the same problem (though I expect it will as it is probably just
a wrapper around the ActiveX object that allows it to be used when
ActiveX is disabled/restricted in the browser)).
There are two good candidates for breaking the circle; the "request"
property of the Activation/Variable object refers to the xml http request
object, so could have - null - assigned to it after the callback function
processes the response, and - onreadystatechange - property of the xml
http request object refers to the anonymous function object, and could be
re-assigned. Unfortunately assigning a non-function to the -
onreadystatechange - property does not work in IE (an allowable quirk of
some ActiveX objects), so the value assigned to break the circle would
have to be a function, but that function could be a simple (and
re-useable) dummy that just did not have a scope chain that held any
references to any xml http request obejcts.
Staying with the Flanagan example, I now have the
following
HTTP.getText = function(url, callback) {
var request = HTTP.newRequest();
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200) {
callback(request.responseText);
}
alert(typeof request.onreadystatechange);
delete request.onreadystatechange;
alert(typeof request.onreadystatechange);
}
}
request.open("GET", url, true);
request.send(null);
};
In Firefox 1.5 both alerts are display "object".
In Internet Explorer 6 both alerts display "unknown".
It is a quirk of many ActiveX objects that their properties return
"unknown" when tested with - typeof -. That is allowed as they are host
objects and the behaviour of - typeof - becomes implementation dependent
when used on host objects. It is also not a problem as such objects
return "undefined" when a property does not exist on the object, so
"unknown" is a positive indicator that there is something there.
In Opera 9 and Safari 2 both alerts display "function".
I expected the first alert to display "function" and the
second to display "undefined". Do you know what is happening
here?
The - delete - operator does not have to be successful. that is, it does
not have to result in the removal of property of an object. It will be
unsuccessful if the property referred to has the internal - DontDelete -
attribute (as is true of all the properties of the Activation/Variable
object), and host objects may give that attribute to their properties if
they want to, or just prevent - delete - from working on them by other
means.
The - delete - operator is actually very little used in javascript, as it
is only reliable on javascript objects. It can be used, for example, to
keep a sparse array sparse, or to re-expose a prototype property that had
been masked, but may examples of its use are predicated on the
fundamental misconception that - delete - operates on the object referred
to by a property (destroying it, as in many class-based OO languages)
while it actually acts upon the object which has the indicated property
(attempting to remove that property from the object.
Generally, assigning - null - will have the effect of stooping a property
from referring to an object. Exceptions, such as IE's issues with
assigning non-function values to - onreadystatechange - mentioned above
are rare, and can be worked around by assigning values of the required
type to replace the existing references with something harless.
Richard.