IE caching previous property positions for deleted properties

B

Brett

Hi,

I'm working on a group of functions which aim to be able to sort a
supplied object. While I understand the ECMAScript spec does not
guarantee for...in iteration order, it does seem to have become a de
facto standard.

However, we encountered an issue in Explorer (and only Explorer) when
trying, within the function, to reassign the old properties with
different (i.e., sorted) values. Even when I explicitly delete all of
the properties on the object beforehand, when I reassign values to the
previously existing properties, the relative position of the keys is
remembered by Explorer (though not by Chrome, Opera, Safari, or
Firefox).

function reverseObj (obj) {
var keys = [], vals = [];
for (var p in obj) {
keys.push(p);
vals.push(obj[p]);
delete obj[p];
}
keys.reverse();
vals.reverse();
for (var i=0; i < keys.length; ++i) {
obj[keys] = vals;
}
}

var assoc = {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'};
reverseObj(assoc); // Does not reverse order in IE (and IE only)

Explorer, as with the other browsers, normally does add new properties
in sequence (at the end), but it breaks this pattern for those
properties which had previously existed on the object (it reassigns
them into the same relative position as before).

Does anyone know of any way to get Explorer to truly forget those
properties ever existed on the passed-in object so the relative
positions of the properties can be freely rearranged?

I wonder if this could even be a minor security issue: if a callback
were instead given to the object after the supposed deletion of
properties, the callback could guess at the properties that had
supposedly been deleted.

While it may be the case that ECMAScript just wasn't meant to be used
in this way, I'd still like for convenience to see if it can be made
to work.

thanks,
Brett
 
B

Brett

Brett said:
...if a callback were instead given to the object after the supposed deletion of
properties, the callback could guess at the properties that had
supposedly been deleted.

Sorry, I meant to say "...if a callback were instead given to the
function, passing it the same object reference after the supposed
deletion of properties..."

Brett
 
W

wilq

Hi,

I'm working on a group of functions which aim to be able to sort a
supplied object. While I understand the ECMAScript spec does not
guarantee for...in iteration order, it does seem to have become a de
facto standard.

However, we encountered an issue in Explorer (and only Explorer) when
trying, within the function, to reassign the old properties with
different (i.e., sorted) values. Even when I explicitly delete all of
the properties on the object beforehand, when I reassign values to the
previously existing properties, the relative position of the keys is
remembered by Explorer (though not by Chrome, Opera, Safari, or
Firefox).

    function reverseObj (obj) {
        var keys = [], vals = [];
        for (var p in obj) {
            keys.push(p);
            vals.push(obj[p]);
            delete obj[p];
        }
        keys.reverse();
        vals.reverse();
        for (var i=0; i < keys.length; ++i) {
            obj[keys] = vals;
        }
    }

    var assoc = {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'};
    reverseObj(assoc); // Does not reverse order in IE (and IE only)

Explorer, as with the other browsers, normally does add new properties
in sequence (at the end), but it breaks this pattern for those
properties which had previously existed on the object (it reassigns
them into the same relative position as before).

Does anyone know of any way to get Explorer to truly forget those
properties ever existed on the passed-in object so the relative
positions of the properties can be freely rearranged?

I wonder if this could even be a minor security issue: if a callback
were instead given to the object after the supposed deletion of
properties, the callback could guess at the properties that had
supposedly been deleted.

While it may be the case that ECMAScript just wasn't meant to be used
in this way, I'd still like for convenience to see if it can be made
to work.

thanks,
Brett


This is trully interesting. I manage to do what you want, but with a
return statement. However this strange behaviour is still there in IE.
Strange hmm... Funny thing is that if you do obj=newObj inside
function it does not change reference correctly, but if you do return
newObj, and then assing function value to a obj = reverseObj(obj) - it
changes this properly... Any explanation for that ?:)




function reverseObj (obj) {
var keys = [], vals = [],retObj={};
for (var p in obj) {
keys.push(p);
vals.push(obj[p]);
}
keys.reverse();
vals.reverse();
for (var i=0; i < keys.length; ++i) {
retObj[keys] = vals;
}
obj=retObj;
return retObj;
}
var assoc = {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'};
var assoc2 = {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'};
assoc = reverseObj(assoc); // Does not reverse order in IE (and IE
only)
reverseObj(assoc2);

var a="",b="";
for (var c in assoc)
a+=c+" ";
for (var c in assoc2)
b+=c+" ";

alert(a);
alert(b);
 
A

Asen Bozhilov

wilq said:
This is trully interesting. I manage to do what you want, but with a
return statement. However this strange behaviour is still there in IE.

The order of enumeration is defined by `object', and is it
implementation depended.
Strange hmm... Funny thing is that if you do obj=newObj inside
function it does not change reference correctly, but if you do return
newObj, and then assing function value to a obj = reverseObj(obj) - it
changes this properly... Any explanation for that ?:)

Absolutely expected behavior. Property `obj' is a property of AO/VO
associated with execution context created when been calling
`reverseObj'. So when execution context finish, VO/AO of that
execution context will be marked for garbage collection, because
doesn't have any reference to AO/VO.
 
J

John G Harris

Hi,

I'm working on a group of functions which aim to be able to sort a
supplied object. While I understand the ECMAScript spec does not
guarantee for...in iteration order, it does seem to have become a de
facto standard.

Javascript has something whose job is to hold values in a particular
order : Array objects. That's what array indexes do : they tell you what
order the values are in. These objects even have a built-in sort method
to save you having to write your own.

However, we encountered an issue in Explorer (and only Explorer) when
trying, within the function, to reassign the old properties with
different (i.e., sorted) values. Even when I explicitly delete all of
the properties on the object beforehand, when I reassign values to the
previously existing properties, the relative position of the keys is
remembered by Explorer (though not by Chrome, Opera, Safari, or
Firefox).
<snip>

Well, both the ES3 and ES5 specifications say about for(... in ... )
that :
"The mechanics and order of enumerating the properties ... is not
specified."
so you can't be surprised if you get into trouble.

Making use of unspecified features of some browsers is irresponsible, as
a lot of web sites demonstrate now that IE8 is here.

John
 
T

Thomas 'PointedEars' Lahn

Brett said:
I'm working on a group of functions which aim to be able to sort a
supplied object. While I understand the ECMAScript spec does not
guarantee for...in iteration order, it does seem to have become a de
facto standard.

You are mistaken. ECMAScript Ed. 3 does not only not guarantee a specific
order, it says explicitly that the order of for-in iteration is
implementation-dependent and that the order is defined by the object (*two*
uncertainties):

| 12.6.4 The for-in Statement
|
| [...]
| The mechanics of enumerating the properties (step 5 in the first
| algorithm, step 6 in the second) is implementation dependent. The
| order of enumeration is defined by the object. [...]
However, we encountered an issue in Explorer (and only Explorer) when

There are dozens of versions of Internet Explorer; there is also Windows
Explorer (still with many versions), and several other products using the
Explorer name. Be specific in your descriptions (e.g., check the `Info'
item in the `?/Help' menu of Internet Explorer, type
'javascript:navigator.userAgent', and post both results).
[...]
Explorer, as with the other browsers, normally does add new properties
in sequence (at the end), but it breaks this pattern for those
properties which had previously existed on the object (it reassigns
them into the same relative position as before).

That is what "implementation-dependent" means; the implementation you are
dealing with here being Microsoft JScript.
Does anyone know of any way to get Explorer to truly forget those
properties ever existed on the passed-in object so the relative
positions of the properties can be freely rearranged?

Unlikely. Use an Array instance if you need an order.

| 4.3.3 Object
|
| An object is a member of the type Object. It is an unordered collection of
^^^^^^^^^^^^^^^^^^^^
| properties each of which contains a primitive value, object, or function.
| [...]

| 15.4 Array Objects
|
| Array objects give special treatment to a certain class of property names.
| A property name P (in the form of a string value) is an array index if and
| only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
| to 2^32−1.

Non-order is also not the only problem with for-in iteration; it iterates
over *all* enumerable properties, including those inherited through the
prototype chain. Be aware of that and provide a filter where necessary
(there is nothing inherently wrong in augmenting prototype objects of built-
in objects as long as you provide a filter, are aware of the augmentation,
and for-in loop over these objects in a consistent way. You would probably
want to provide it for user-defined objects, too.)

[applied correction from
I wonder if this could even be a minor security issue: [if a callback were
instead given to the function, passing it the same object reference after
the supposed deletion of properties], the callback could guess at the
properties that had supposedly been deleted.

I do not think the costs of finding out merit an exploit. Remember that
property names may be of arbitrary composition and length.
While it may be the case that ECMAScript just wasn't meant to be used
in this way, I'd still like for convenience to see if it can be made
to work.

It was meant to be used this way.


PointedEars
 
B

Brett

@PointedEars and @Asen: Thank you for your very precise answers.
Specific replies to PointedEars below.

@wilq: Thanks for the workaround. Was trying to imitate an API which
worked solely by reference, but I guess I'll have to copy the object
as you suggest.

@John: I know that arrays in JavaScript are intended for this purpose,
but I find it convenient (and more intuitive) to be able to keep
ordered pairs of information tied together (as is possible in some
languages). Before HTML5, DOM Level 0 had not been formally specified
either, so I don't think it is necessarily irresponsible to rely on
non-standard features if they are effectively standard. But I see now
in this instance, that this is not the case.
There are dozens of versions of Internet Explorer; there is also Windows
Explorer (still with many versions), and several other products using the
Explorer name. Be specific in your descriptions (e.g., check the `Info'
item in the `?/Help' menu of Internet Explorer, type
'javascript:navigator.userAgent', and post both results).

Under Help->About (if that's what you mean--that's all I can see in my
Vista version), there is version 8.0.6001.18828IC

For userAgent, I have:

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0;
SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR
3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30729; yie8)
Unlikely. Use an Array instance if you need an order.

Yeah, thanks. I see IE has a CollectGarbage() method, but from what I
can tell, that only apparently works with whole objects whose
references have all been removed (and of course, it is not a standard
function).

Thanks again...
 
J

Jim Ley

@John: I know that arrays in JavaScript are intended for this purpose,
but I find it convenient (and more intuitive) to be able to keep
ordered pairs of information tied together (as is possible in some
languages).

obj=new Array();

// Add pairs with:

obj.push({"name":value});
obj["name"]=value;

Then so long as none of your names are numeric - if they are, or could
be simply prefix the key one with an underscore or similar always -
you get the ability to iterate over an ordered list with regular array
syntax, and access by name.

Jim.
 
T

Thomas 'PointedEars' Lahn

Brett said:
["@John:" etc.]

Please don't. See my e-mail for details.
I know that arrays in JavaScript are intended for this purpose,
but I find it convenient (and more intuitive) to be able to keep
ordered pairs of information tied together (as is possible in some
languages).

You can also have that with ECMAScript implementations, for example:

var a = [
{foo: "bar"},
{baz: 42}
];

The tradeoff is slower access to the information, but that can be mitigated
by using a hash function.
Before HTML5, DOM Level 0 had not been formally specified
either, so I don't think it is necessarily irresponsible to rely on
non-standard features if they are effectively standard.

In my experience, to perceive something that is not a standard as
"effectively standard" is often indicative of superficial testing.
But I see now in this instance, that this is not the case.

It seldom is.
Under Help->About (if that's what you mean--

Yes, labels vary.
that's all I can see in my Vista version), there is version
8.0.6001.18828IC

For userAgent, I have:

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0;
SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR
3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30729; yie8)

Thanks. Apparently it is an IE 8.0 for Windows Vista on a Windows Media
Center PC, optimized for Yahoo!, working in Standards Mode (as indicated by
the "MSIE 8.0"). It would be interesting to know if other versions of IE 8,
or IE 8 in Compatibility Mode ("MSIE 7.0") showed the same symptoms.
Yeah, thanks. I see IE has a CollectGarbage() method, but from what I
can tell, that only apparently works with whole objects whose
references have all been removed

Yes, garbage collection has nothing to do with this. It is the fact that
the object that had the properties still exists that causes this behavior.
(and of course, it is not a standard function).
ACK

Thanks again...

You are welcome.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Jim said:
obj=new Array();

Should be

var obj = new Array();

or (equally compatible these days¹)

var obj = [];
// Add pairs with:

obj.push({"name":value});

In this example, the less compatible Array.prototype.push() call¹ is
unnecessary:

var obj = new Array(
{"name": value}
);

or

var obj = [
{"name": value}
];
obj["name"]=value;

Then so long as none of your names are numeric - if they are, or could
be simply prefix the key one with an underscore or similar always -
you get the ability to iterate over an ordered list with regular array
syntax, and access by name.

Built-in non-numeric properties also need to be taken care of as they would
be overwritten otherwise. But the general disadvantage of that approach is
that the value needs to be duplicated which allows for inconsistencies. It
would be better if the non-numeric property referred to the user data; here:

obj["name"] = obj[0];

In general:

obj = {
_data: [],

add: function(name, value) {
var o = {};
o[name] = value;
_data.push(o);
o = null;
_data[name] = data[data.length - 1];
},

get: function(name) {
return _data[name];
}
};

Then:

obj.add("name", value);

/* value */
obj.get("name");

Incidentally, that is basically what collection implementations (e.g., mine)
do.

P.S.: Nice to read you again :)


PointedEars
___________
¹ See the ECMAScript Support Matrix: <http://PointedEars.de/es-matrix>
 
T

Thomas 'PointedEars' Lahn

Thomas said:
In general:

obj = {
_data: [],

add: function(name, value) {
var o = {};
o[name] = value;

var _data = this._data;
_data.push(o);
o = null;
_data[name] = data[data.length - 1];

_data[name] = _data[_data.length - 1];
},

get: function(name) {
return _data[name];
}
};

PointedEars
 
J

Jim Ley

In this example, the less compatible Array.prototype.push() call¹ is
unnecessary:

Only if you assume the code was whole, rather than just an example of
how to add to such an object. You're right of course though.
It
would be better if the non-numeric property referred to the user data; here:

obj["name"] = obj[0];

Probably, depends what you mean by better, since later accessing of
the value would take an extra resolution. But that is what I'd really
do. Not sure why I didn't write it. being out of touch I guess :)
In general:

obj = {
_data: [],

add: function(name, value) {
var o = {};
o[name] = value;
_data.push(o);
o = null;
_data["_"+name] = data[data.length - 1];
},

get: function(name) { return _data["_"+name]
}
};

Wouldn't that change above be better, to prevent anyone from creating
length / numbered properties by accident?

Jim.
 
T

Thomas 'PointedEars' Lahn

Jim said:
Thomas said:
It would be better if the non-numeric property referred to the user
data; here:

obj["name"] = obj[0];

Probably, depends what you mean by better, since later accessing of
the value would take an extra resolution. But that is what I'd really
do. Not sure why I didn't write it. being out of touch I guess :)

Happens to the best of us :)

[Implemented corrections from said:
In general:

obj = {
_data: [],

add: function(name, value) {
var o = {};
o[name] = value;
var _data = this._data;
_data.push(o);
o = null;
_data["_" + name] = _data[_data.length - 1];
},

get: function(name) { return this._data["_" + name];
}
};

Wouldn't that change above be better, to prevent anyone from creating
length / numbered properties by accident?

The change assumes a numeric value that losslessly converts to an unsigned
32-bit integer value was passed by accident. I would rather not make that
assumption, in order to allow people to set values for specific indexes
(much like the bracket property accessor with collection implementation).

In addition, simply prefixing with `_' has greater a chance to access built-
in properties in a harmful way if the property name is not numeric.

The Ultimate Solution[tm] would probably involve a flag to be set to
determine whether or not numeric names are allowed, and an approach that
tries hard to avoid overwriting built-in properties (see my Map
implementation for the latter.)


PointedEars
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Fri, 27 Nov 2009 20:22:00, John G Harris
Well, both the ES3 and ES5 specifications

Does the actual *ratified* ES5 specification yet exist? Until it does,
one should not purport to cite it.

ISTM that ECMA does not understand, or at least write, English as well
as it should. I now have TWO final drafts of ECMA 5, dated April and
September. That cannot be correct : and what if the General Assembly
says "quite good, but needs some changes - produce another draft."

<http://www.ecma-international.org/publications/standards/Standard.htm>
currently offers ECMA 263-3 Dec 1999. They do not there offer ECMA
262-3 Mar 2000.
 
J

John G Harris

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Fri, 27 Nov 2009 20:22:00, John G Harris


Does the actual *ratified* ES5 specification yet exist?

Obviously I was referring to the current releases of these two
documents. In case anyone doesn't know, ES5 is currently
"Final Draft 5th Edition / September 2009",
obtainable at
<http://www.ecmascript.org/docs/tc39-2009-043.pdf>.
(It seems the ECMA site has lost its copy.)

Until it does,
one should not purport to cite it.

There are occasions when it's right to refer to the current draft of the
next edition. One is when you need to point out that some feature being
complained about is likely to change in the next edition, or not change,
as the case may be.

This is the case here. In ES3 the enumeration order of properties in
for-in is arbitrary. The ES4 Outline says that the enumeration order is
likely to be defined, on the grounds that it is defined in some popular
browsers. Then the ES5 Final Draft says it's likely to remain arbitrary.
It looks as though Microsoft realised they couldn't change it.

ISTM that ECMA does not understand, or at least write, English as well
as it should. I now have TWO final drafts of ECMA 5, dated April and
September. That cannot be correct :

I doubt if the problem is understanding or writing English. I've seen
people in a thoroughly English organisation publish a replacement draft
with no issue or date on it. They just assumed that people would
immediately throw the previous draft away. At least ECMA put an
identifying date on it. Calling the earlier one Final can't be helped if
no-one expected changes at the time it was promulgated.

and what if the General Assembly
says "quite good, but needs some changes - produce another draft."

According to Crockford some ECMA members might ask the Ecma General
Assembly to reject the ES5 Draft in its current form.

<http://www.ecma-international.org/publications/standards/Standard.htm>
currently offers ECMA 263-3 Dec 1999. They do not there offer ECMA
262-3 Mar 2000.

The ECMA web site's List of standards doesn't mention a Mar 2000
version. Where did you find it ?

John
 
B

Brett

Thomas said:
Thanks. Apparently it is an IE 8.0 for Windows Vista on a Windows Media
Center PC, optimized for Yahoo!, working in Standards Mode (as indicated by
the "MSIE 8.0"). It would be interesting to know if other versions of IE 8,
or IE 8 in Compatibility Mode ("MSIE 7.0") showed the same symptoms.

In compatibility mode in IE 8 (and confirming that the option did also
cause the user agent to show as MSIE 7.0), I do get the same behavior.
 
B

Brett

Jim said:
@John: I know that arrays in JavaScript are intended for this purpose,
but I find it convenient (and more intuitive) to be able to keep
ordered pairs of information tied together (as is possible in some
languages).

obj=new Array();

// Add pairs with:

obj.push({"name":value});
obj["name"]=value;

Then so long as none of your names are numeric - if they are, or could
be simply prefix the key one with an underscore or similar always -
you get the ability to iterate over an ordered list with regular array
syntax, and access by name.

Thanks. Good to have a workaround even if it is a bit cumbersome.

I imagine one could also allow numeric properties by requiring key
access to be done in a specific way maybe like:

obj.push({"name":value});
obj._ = {};
obj._["name"]=value;
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Sun, 29 Nov 2009 17:43:42, John G Harris
Obviously I was referring to the current releases of these two
documents. In case anyone doesn't know, ES5 is currently
"Final Draft 5th Edition / September 2009",
obtainable at
<http://www.ecmascript.org/docs/tc39-2009-043.pdf>.
(It seems the ECMA site has lost its copy.)



There are occasions when it's right to refer to the current draft of the
next edition.

Correct. But not *as* the next edition.

I doubt if the problem is understanding or writing English. I've seen
people in a thoroughly English organisation publish a replacement draft
with no issue or date on it. They just assumed that people would
immediately throw the previous draft away.

That's mere stupidity. Any formal published draft or document should be
fully identifiable.

At least ECMA put an
identifying date on it. Calling the earlier one Final can't be helped if
no-one expected changes at the time it was promulgated.

No. A draft can only sensibly be annotated as a final draft when the
document of which it is a draft is formally accepted, ratified,
released, or whatever. Before that, it can only be a dated release
candidate.

According to Crockford some ECMA members might ask the Ecma General
Assembly to reject the ES5 Draft in its current form.

Nicely illustrating my point. I'd like to see canvas routines in it.

ASIDE: Has anyone got dashed-line code for canvas?


The ECMA web site's List of standards doesn't mention a Mar 2000
version. Where did you find it ?

I don't know. But I can say where a copy is. The link in my <js-
index.htm> leads directly to <http://www.mozilla.org/js/language/E262-3.
pdf> (1,217,793 bytes). The FAQ links to <http://www.ecma-international
..org/publications/files/ECMA-ST/ECMA-262.pdf> (720,951 bytes).

The FAQ version, unlike the later one, lacks a section numbered 15.9.1.7
and has two numbered 15.9.1.9.

Does anyone have a PDF text comparer? Although the texts are similar
(perhaps Mozilla includes 0.5MB of font?), they clearly cannot be
presumed identical.

There is also <http://www.mozilla.org/js/language/E262-3-errata.html>
(dated Monday, June 9, 2003; says Last modified Tuesday, January 15,
2008); but it sayeth not which ECMAScript Edition 3 it is Errata for.
 
M

Michael Haufe (\TNO\)

That's mere stupidity. Any formal published draft or document should be
fully identifiable. ....
Does anyone have a PDF text comparer? Although the texts are similar
(perhaps Mozilla includes 0.5MB of font?), they clearly cannot be
presumed identical.

In regards to the ES specification comments, the current document
pending
ratification is available below along with older versions with change
history:
http://wiki.ecmascript.org/doku.php?id=es3.1:es3.1_proposal_working_draft

In December the vote of yes or no will occur. I believe the primary
antagonist to this specification is IBM due to the lack of decimal
support
in this version. The probability is in favor of this passing though I
think.
Even if it does not, browser vendors are already implementing it. In
FireFox
and Rhino for example, it will be implemented as part of JavaScript
1.9.
Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=429508
Nicely illustrating my point. I'd like to see canvas routines in it.

Any DOM related manipulation doesn't belong in that particular
standard. On that
note though, there is talk if adding a ByteArray object which could
vastly improve
performance. Reference:
http://wiki.ecmascript.org/doku.php?id=strawman:strawman
https://bugzilla.mozilla.org/show_bug.cgi?id=497795
ASIDE: Has anyone got dashed-line code for canvas?

I just wrote one for you here as an example:
http://thenewobjective.com/temp/dashLine.html

No doubt it could be improved, but it was a bit off the cuff and my
high school math is rusty.
 
B

Bwig Zomberi

Dr said:
In comp.lang.javascript message<[email protected]
8924D9443D28E23ED5CD>, Fri, 27 Nov 2009 20:22:00, John G Harris


Does the _actual_ *ratified* ES5 specification yet exist? Until it does,
one should not _purport_to_ cite it.

Does the purported *ratified* ES5 specification yet exist? Until it
does, one should not actually cite it
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top