Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

new Array(76)

2 views
Skip to first unread message

ric...@tortoise.demon.co.uk

unread,
Nov 18, 2009, 3:50:17 PM11/18/09
to
If I can use the syntax

var MyArray = new Array(76)

to create an array with 76 objects,
and I can also use the syntax

var MyArray2 = new Array(0,1,2,3,4)

to create an array containing 5 integer elements,
how is one to know if

var MyArray = new Array(76)

creates an array with 76 objects or one containing a single integer of
value 76?

Thanks for any illumination

Richard

Stefan Weiss

unread,
Nov 18, 2009, 4:09:17 PM11/18/09
to

The case where the Array constructor is called with exactly one integer
argument gets special treatment; all other cases interpret the arguments
as elements to be added to the new array. Some people think it was a bad
idea to specify this inconsistent and unintuitive behavior for the Array
constructor. On the other hand, it's rarely necessary to call 'new
Array'; most of the time, you're better off using an array literal like

var myArray2 = [0, 1, 2, 3, 4];

That's unambiguous and shorter, too. Off the top of my head, I can only
think of two situations where 'new Array' would be useful:

- sparse arrays, and
- var fourFoos = new Array(5).join("foo"); // a string repeat trick

There were also browser bugs associated with the 'new Array(integer)'
form; I'm not sure which browser it was (some older IE, I think).


cheers,
stefan

ric...@tortoise.demon.co.uk

unread,
Nov 18, 2009, 4:15:30 PM11/18/09
to
On Wed, 18 Nov 2009 22:09:17 +0100, Stefan Weiss
<krewe...@gmail.com> wrote:

>The case where the Array constructor is called with exactly one integer
>argument gets special treatment; all other cases interpret the arguments
>as elements to be added to the new array.

Thank you for the clarification Stefan.

Regards
Richard

Lasse Reichstein Nielsen

unread,
Nov 18, 2009, 4:27:33 PM11/18/09
to
Stefan Weiss <krewe...@gmail.com> writes:

> Off the top of my head, I can only
> think of two situations where 'new Array' would be useful:
>
> - sparse arrays, and
> - var fourFoos = new Array(5).join("foo"); // a string repeat trick

Some Javascript implementations actually assumes that the user knows
what he is doing, so "new Array(40000)" pre-allocates room for 40000
elements (i.e., expects a dense array, whereas
"var a = new Array();a.length=40000;" expects the array to be sparse).

/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

Asen Bozhilov

unread,
Nov 18, 2009, 4:36:33 PM11/18/09
to
Stefan Weiss wrote:

> That's unambiguous and shorter, too. Off the top of my head, I can only
> think of two situations where 'new Array' would be useful:

See that entries how JScript optimize resolving properties from array
objects:
<URL: http://blogs.msdn.com/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx>
<URL: http://blogs.msdn.com/jscript/archive/2008/04/08/performance-optimization-of-arrays-part-ii.aspx>


Thomas 'PointedEars' Lahn

unread,
Nov 18, 2009, 7:48:54 PM11/18/09
to
ric...@tortoise.demon.co.uk wrote:

> If I can use the syntax
>
> var MyArray = new Array(76)

The identifier of the variable should start lowercase as the referred object
cannot be [[Construct]]ed and is not a factory.



> to create an array with 76 objects,

You cannot. The ECMAScript Language Specification, Edition 3 Final,
mandates in section 15.4.2 (specifically, subsection 15.4.2.2) that if the
argument list has the length one (and several other preconditions are met),
the resulting array will have a `length' property with the argument value
converted to an unsigned 32-bit integer value (converted to an IEEE-754
floating point number for storage); here: 76. Nothing more, nothing less.

If you are lucky, the implementation reserves sizeof(pointer) * 76 bytes +
object metadata storage for the array on the heap, but there is no specified
requirement for that. In any case, the initial array would not store
objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
8.1). Later it could store object _references_ (which are likely to be
implemented as pointers in a lower-level language).

However, there have been implementations that did not follow the
Specification in that regard and created an array with one number-typed
element. So it is better to avoid this type of constructor call and use

var myArray = new Array();
myArray.length = 76;

(as Lasse said) or, equally compatible these days¹,

var myArray = [];
myArray.length = 76;

to encourage the implementation to allocate more memory for storing as many
array elements. If it works as described, it should increase filling
performance as compared to the solution without `length' assignment),
especially if the values you are storing are primitive values (if not,
faster array filling is probably mitigated by the cost for object memory
allocation).


PointedEars
___________
¹ See also: <http://PointedEars.de/es-matrix>
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)

Garrett Smith

unread,
Nov 18, 2009, 9:33:01 PM11/18/09
to
Thomas 'PointedEars' Lahn wrote:
> ric...@tortoise.demon.co.uk wrote:
>
[...]

> var myArray = new Array();
> myArray.length = 76;
>
> (as Lasse said) or, equally compatible these days¹,
>
> var myArray = [];
> myArray.length = 76;
>

This can help performance a little in a loop that populates an array.
If the loop has to add to the Array, it avoids a step of set the length
property (step 10 of Array [[Put]]).
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Jorge

unread,
Nov 19, 2009, 4:16:11 AM11/19/09
to
On Nov 19, 1:48 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
> (...)

> If you are lucky, the implementation reserves sizeof(pointer) * 76 bytes +
> object metadata storage for the array on the heap, but there is no specified
> requirement for that.  In any case, the initial array would not store
> objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
> 8.1).  Later it could store object _references_ (which are likely to be
> implemented as pointers in a lower-level language).
> (...)

> to encourage the implementation to allocate more memory for storing as many
> array elements.  If it works as described, it should increase filling
> performance as compared to the solution without `length' assignment),
> especially if the values you are storing are primitive values (if not,
> faster array filling is probably mitigated by the cost for object memory
> allocation).
> (...)

LOL, all of the above looks very much like a copy-paste from c.l.C
JS Arrays and JS objects are very much alike, almost ===, but have
absolutely nothing to do with C-ish style arrays...

For example, saying a you did that "If you are lucky, the
implementation reserves sizeof(pointer) * 76 bytes in the heap" is a
nonsense for arrays like these in JS whose elements can hold data of
any type -unlike in C- and whose elements might not even exist (thus
the saying that they can be "sparse"). E.g. if things were as you call
"being lucky", a 2^32 elements sparse Array of 4 bytes pointers would
mean an malloc(4*(2^32)) of 16GB ! which I'd rather call "being
*unlucky*". :-)

a= new Array(2^32);
a.length; //-> 4294967296
//Nothing "rare" happens, no 16GBytes get allocated nowhere (do a top
& see).
--
Jorge.

Jorge

unread,
Nov 19, 2009, 4:53:10 AM11/19/09
to
On Nov 19, 10:16 am, Jorge <jo...@jorgechamorro.com> wrote:
> (...)

> a= new Array(2^32);
> a.length; //-> 4294967296
> //Nothing "rare" happens, no 16GBytes get allocated nowhere (do a top
> & see).

Well, well:

javascript:a= Math.pow(2,32)-1; b= new Array(a); alert([a, b.length]);
-> 4294967295, 4294967295
--
Jorge.

Thomas 'PointedEars' Lahn

unread,
Nov 19, 2009, 4:57:57 AM11/19/09
to
Jorge wrote:

> Thomas 'PointedEars' Lahn wrote:
>> (...)
>> If you are lucky, the implementation reserves sizeof(pointer) * 76 bytes
>> + object metadata storage for the array on the heap, but there is no
>> specified requirement for that. In any case, the initial array would not
>> store objects, but `undefined' values, of the primitive `Undefined' type
>> (ES3F, 8.1). Later it could store object _references_ (which are likely
>> to be implemented as pointers in a lower-level language).
>> (...)
>> to encourage the implementation to allocate more memory for storing as
>> many array elements. If it works as described, it should increase
>> filling performance as compared to the solution without `length'
>> assignment), especially if the values you are storing are primitive
>> values (if not, faster array filling is probably mitigated by the cost
>> for object memory allocation).
>> (...)
>
> LOL, all of the above looks very much like a copy-paste from c.l.C

It is not.

> JS Arrays and JS objects are very much alike, almost ===, but have
> absolutely nothing to do with C-ish style arrays...

And I have not said or implied that.



> For example, saying a you did that "If you are lucky, the
> implementation reserves sizeof(pointer) * 76 bytes in the heap" is a
> nonsense for arrays like these in JS whose elements can hold data of
> any type

If you had read more thoroughly, you would have noticed that internally, in
the lower-level language of the implementation (even a JavaScript
implementation in JavaScript would be based on such a language; possibly,
but not necessarily C), arrays would not hold data of any type, but would
very likely use pointers to refer to the memory allocated for non-primitive
values and primitive values that require more memory than the average case.

> -unlike in C-

In C, an array can hold generic void pointers, can it not?

> and whose elements might not even exist (thus the saying that they can be
> "sparse"). E.g. if things were as you call "being lucky", a 2^32 elements
> sparse Array of 4 bytes pointers would mean an malloc(4*(2^32)) of 16GB !
> which I'd rather call "being *unlucky*". :-)
>
> a= new Array(2^32);
> a.length; //-> 4294967296

That is not what happens, of course (2^32 === 34), but I'll bite.

> //Nothing "rare" happens, no 16GBytes get allocated nowhere (do a top
> & see).

So, assuming

var a = new Array(Math.pow(2, 32));

worked as implied by you -- which it it does not; a RangeError exception
is thrown because ToUint32(Math.pow(2, 32)) !== Math.pow(2, 32) --,
implementations would be clever enough to prevent this kind of nonsense.
That would not prove anything.

In any case, I have merely made an assumption, not a definitive statement.
Get a life.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

Jorge

unread,
Nov 19, 2009, 6:15:27 AM11/19/09
to
On Nov 19, 10:57 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
> (...)

> In any case, I have merely made an assumption, not a definitive statement.

A bad assumption, yes. Perhaps you have now realized it.

> Get a life.

Take it easy, Pointy. Nobody is perfect, not even you. Perhaps you
have now realized this too... :-)
--
Jorge.

Jorge

unread,
Nov 19, 2009, 6:22:51 AM11/19/09
to
On Nov 19, 10:57 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
>

> > For example, saying a you did that "If you are lucky, the
> > implementation reserves sizeof(pointer) * 76 bytes in the heap" is a
> > nonsense for arrays like these in JS whose elements can hold data of
> > any type
>
> If you had read more thoroughly, you would have noticed that internally, in
> the lower-level language of the implementation (even a JavaScript
> implementation in JavaScript would be based on such a language; possibly,
> but not necessarily C), arrays would not hold data of any type, but would
> very likely use pointers to refer to the memory allocated for non-primitive
> values and primitive values that require more memory than the average case.
>
> > -unlike in C-
>
> In C, an array can hold generic void pointers, can it not?

You can have an array whose elements are all pointers and it would be
an array whose elements are each of type (any type)*. But you can't
have an array whose elements are each of type (any type).
--
Jorge.

Jorge

unread,
Nov 19, 2009, 6:29:48 AM11/19/09
to
On Nov 19, 10:57 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
>

> So, assuming
>
>   var a = new Array(Math.pow(2, 32));
>
> worked as implied by you -- which it it does not; a RangeError exception
> is thrown because ToUint32(Math.pow(2, 32)) !== Math.pow(2, 32) --,
> implementations would be clever enough to prevent this kind of nonsense.
>
> That would not prove anything.

Executing:

a= new Array(Math.pow(2, 32)-1);

Proves whether or not "you're lucky enough" to get 16GB of pre-
allocated memory, as you said.
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 19, 2009, 8:35:31 AM11/19/09
to
Guys, what the "16GB" and "allocation of pointer" are you talking
about? Modification of the `length` property is - only modification of
the `length` property. Nothing has done with allocation with elements
(except if `length` becomes less, then some elements will be deleted
from the end).

Array object (on implementation level) - the same data structure as
other objects (simple object). So even if `toString` shows several
elisions with commas, that doesn't mean that there was any allocation
or sort of:

var a = Array(5);
alert(a); ',,,,'
a.join('*'); // ****

But that's only result of the concrete algorithm's work which has
inside simple `for` loop which depends on current `length` property.
There's no any allocation of anything, it's just the same object as
others, and having `lenght` = 3, we'll have `a[0] === a[100]` just
because of [[Get]] method which returns `undefined` in this case.

On implementation level, more complex structure is used as usually for
object (not the C-arrays with allocation the pointers of sort of,
that's nonsense) as arrays are sparse and can have different from
`string-digit` properties. So, it's sort of hash-map (as usually if to
analyze codes of some implementations), or at least dynamic linked
list are used for that aims.

Swifty

unread,
Nov 19, 2009, 9:30:18 AM11/19/09
to
Lasse Reichstein Nielsen wrote:
> Some Javascript implementations actually assumes that the user knows
> what he is doing

No wonder I've been having so much trouble!

--
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk

Thomas 'PointedEars' Lahn

unread,
Nov 19, 2009, 8:13:34 AM11/19/09
to
Jorge wrote:

> Thomas 'PointedEars' Lahn wrote:
>> So, assuming
>>
>> var a = new Array(Math.pow(2, 32));
>>
>> worked as implied by you -- which it it does not; a RangeError exception
>> is thrown because ToUint32(Math.pow(2, 32)) !== Math.pow(2, 32) --,
>> implementations would be clever enough to prevent this kind of nonsense.
>>
>> That would not prove anything.
>
> Executing:
>
> a= new Array(Math.pow(2, 32)-1);
>
> Proves whether or not "you're lucky enough" to get 16GB of pre-
> allocated memory, as you said.

No.


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

Dr J R Stockton

unread,
Nov 19, 2009, 9:24:32 AM11/19/09
to
In comp.lang.javascript message <j1n8g5d17h5s0bpa3dbtrao5qrv31kgdmn@4ax.
com>, Wed, 18 Nov 2009 20:50:17, ric...@tortoise.demon.co.uk posted:

>how is one to know if
>
>var MyArray = new Array(76)
>
>creates an array with 76 objects or one containing a single integer of
>value 76?

You have asked (intentionally or otherwise) a specific question; and,
at about 23:49 yesterday, that question had not been answered.

The answer is that one reads ISO/IEC 16262 (or ECMA 262) to see what is
specified to occur (links in the FAQ & on my site); and one tests in
browsers to see what actually happens (in this case they can be expected
to agree); and one can read JavaScript books (none are infallible) and
Web sites (most are worse); and one can ask here.

No argument : zero-size array
One argument : array of that size
More arguments : array with that content.

White on black, at standard size, is hard to read; your brother seems to
know better, though those links don't seem to work (using Firefox).
Your Devonian is missing, 404. Your graphic files, BMP, are too big;
Windows Paint can save in more compact formats.

My pages, in site root, need include1.js, want styles-a.css :
<js-grphx.htm> - script to canvas to visible saveable PNG.
<sitedata.htm> - plots Demon count and quota usage from local record.
<linxchek.htm> - checks local links, anchors, dates in master copy.

--
(c) John Stockton, nr London UK. ?@merlyn.demon.co.uk DOS 3.3, 6.20; WinXP.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.

Dmitry A. Soshnikov

unread,
Nov 19, 2009, 2:03:27 PM11/19/09
to
On Nov 19, 5:24 pm, Dr J R Stockton <reply0...@merlyn.demon.co.uk>
wrote:

> [...]


> One argument : array of that size

> [...]

Only if argument is an correct number, otherwise will be array with
`length = 1` and `array[0] = argument` ;)

Luuk

unread,
Nov 19, 2009, 3:00:04 PM11/19/09
to
ric...@tortoise.demon.co.uk schreef:

see example at http://www.w3schools.com/JS/js_obj_array.asp

a little changed it looks like this:
<html>
<body>

<script type="text/javascript">
var mycars = new Array(1);
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";
mycars[5] = "VW";

for (i=0;i<mycars.length;i++)
{
document.write(mycars[i] + "<br />");
}
</script>

</body>
</html>


the line: var mycars = new Array(1);
create an array of 1 (or 2?) elements

mycars[2] =.... adds a new (third) element to the array

mycars[5] =.... adds a new (sixth) element to the array, because
mycars[4] and mycars[3] are create automagically....


--
Luuk

Dmitry A. Soshnikov

unread,
Nov 19, 2009, 3:18:43 PM11/19/09
to
On Nov 19, 11:00 pm, Luuk <l...@invalid.lan> wrote:

> [...]


> because mycars[4] and mycars[3] are create automagically....

> [...]

[4] and [3] won't be created. What you assign, exactly that will be
created. Array object has the same structure as other objects, and
array indexes - are just property names. There're only a few (but
important) things that discriminates arrays from other objects -
that's automatically handled `length` property, special [[Put]]
method, and so other.


Lasse Reichstein Nielsen

unread,
Nov 19, 2009, 3:41:34 PM11/19/09
to
Luuk <lu...@invalid.lan> writes:

...


> var mycars = new Array(1);
> mycars[0] = "Saab";
> mycars[1] = "Volvo";
> mycars[2] = "BMW";
> mycars[5] = "VW";
>
> for (i=0;i<mycars.length;i++)
> {
> document.write(mycars[i] + "<br />");
> }
> </script>
>
> </body>
> </html>
>
>
> the line: var mycars = new Array(1);
> create an array of 1 (or 2?) elements

No elements, but a length of 1. You can check that there are no elements:
alert( 0 in mycars ); // alerts false.

> mycars[2] =.... adds a new (third) element to the array

Correct. Adds a third element and increases the length to 3.

> mycars[5] =.... adds a new (sixth) element to the array, because
> mycars[4] and mycars[3] are create automagically....

Adds a fourth element at position 5 (position 3 and 4 are still
empty), and sets length to 6.

ric...@tortoise.demon.co.uk

unread,
Nov 19, 2009, 4:31:09 PM11/19/09
to
On Thu, 19 Nov 2009 14:24:32 +0000, Dr J R Stockton
<repl...@merlyn.demon.co.uk> wrote:

>White on black, at standard size, is hard to read; your brother seems to
>know better, though those links don't seem to work (using Firefox).
>Your Devonian is missing, 404. Your graphic files, BMP, are too big;
>Windows Paint can save in more compact formats.
>

Thanks. I'll pass your comments on to my children :-)

Thomas 'PointedEars' Lahn

unread,
Nov 23, 2009, 6:42:04 AM11/23/09
to
Dmitry A. Soshnikov wrote:

> On implementation level, more complex structure is used as usually for
> object (not the C-arrays with allocation the pointers of sort of,
> that's nonsense) as arrays are sparse and can have different from
> `string-digit` properties. So, it's sort of hash-map (as usually if to
> analyze codes of some implementations), or at least dynamic linked
> list are used for that aims.

And now make an educated guess how a hash map or a linked list is
implemented in a lower-level language like C/C++.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

David Mark

unread,
Nov 23, 2009, 6:56:29 AM11/23/09
to

Yes, created a single element array with that integer. I don't
remember which either (old though), but I do remember seeing this
practice used recently (in GoogClosure perhaps). ISTM that it is
safer to set the length property if optimization is the goal. I don't
find much use for new Array either.

Dmitry A. Soshnikov

unread,
Nov 23, 2009, 1:16:12 PM11/23/09
to
On Nov 23, 2:42 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> [...]


> And now make an educated guess how a hash map or a linked list is
> implemented in a lower-level language like C/C++.
>

Thanks, I know it and it's another question, but what you was talking
about ES (and I remind: "If you are lucky, the implementation reserves


sizeof(pointer) * 76 bytes + object metadata storage for the array on

the heap") - nothing of this is about ES, no any allocation is taking
place, so learn ES deeper ;)~

Jorge

unread,
Nov 23, 2009, 4:20:18 PM11/23/09
to
On Nov 23, 12:42 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
>

> And now make an educated guess how a hash map or a linked list is
> implemented in a lower-level language like C/C++.
>

Blah blah blah.
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 23, 2009, 4:43:41 PM11/23/09
to

Thomas 'Blah blah blah' Lahn? It... sounds :P

P.S.: Just kidding, nevermind, it's friendly ;)

Thomas 'PointedEars' Lahn

unread,
Nov 23, 2009, 7:52:35 PM11/23/09
to
"Dmitry A. Soshnikov" wrote:

> Thomas 'PointedEars' Lahn wrote:
> > [...]
> > And now make an educated guess how a hash map or a linked list is
> > implemented in a lower-level language like C/C++.
>
> Thanks, I know it

I doubt that. If you knew, you would not have opposed my mentioning
pointer allocation in this context.

> and it's another question, but what you was talking
> about ES (and I remind: "If you are lucky, the implementation reserves
> sizeof(pointer) * 76 bytes + object metadata storage for the array on
> the heap") - nothing of this is about ES, no any allocation is taking
> place, so learn ES deeper ;)~

I have never said that the (ECMAScript) Specification makes such a
requirement; in fact, I was referring explicitly only to the
possibilities for an implementation.

Before trying to lecture others, you better learn to read (and write).


PointedEars

Dmitry A. Soshnikov

unread,
Nov 24, 2009, 3:49:03 AM11/24/09
to
On Nov 24, 3:52 am, "Thomas 'PointedEars' Lahn" <PointedE...@web.de>
wrote:

> "Dmitry A. Soshnikov" wrote:
> > Thomas 'PointedEars' Lahn wrote:
> > > [...]
> > > And now make an educated guess how a hash map or a linked list is
> > > implemented in a lower-level language like C/C++.
>
> > Thanks, I know it
>
> I doubt that.
>

That probs are only yours ;)

> I have never said that the (ECMAScript) Specification makes such a
> requirement; in fact, I was referring explicitly only to the
> possibilities for an implementation.

In fact, even guessing about implementation, that is already nonsense,
as there's no any element created (that's in ES) and no need to
allocated some pointers.

> In any case, the initial array would not store
> objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
> 8.1).

Also wrong, there's no any value (not even `undefined`), so learn ES
deeper, then will talk in manner in which you're trying ;)

> Before trying to lecture others, you better learn to read (and write).
>

That's also just your issue, have a luck ;)

Jorge

unread,
Nov 24, 2009, 6:01:19 AM11/24/09
to
On Nov 24, 1:52 am, "Thomas 'PointedEars' Lahn" <PointedE...@web.de>
wrote:
> (...)

> Before trying to lecture others, you better learn to read (and write).

Pointy: He's saying -and rightly so- that you've put your foot in your
-rather big- mouth, again. (HTH).

Dmitry: He can't/won't ever admit it, impeded as he is by some acute -
I'm the best, the one and only, super-mega-Pointy- pathological disease
(s). Let's just wish him to get well, soon.
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 24, 2009, 6:47:43 AM11/24/09
to
On Nov 24, 2:01 pm, Jorge <jo...@jorgechamorro.com> wrote:

> [...]


> Dmitry: He can't/won't ever admit it, impeded as he is by some acute -
> I'm the best, the one and only, super-mega-Pointy- pathological disease
> (s). Let's just wish him to get well, soon.
>

Don't be worry, I just have fun. I need to see just once or twice
somebody's answer/code to understand his skill in ES. So don't make PR
to Thomas 'PointedEars' Lahn, he just has now youthful maximalism
(hope this maximalism will gone later). As I mentioned already Thomas
'PointedEars' Lahn knows ES a bit deeper than casual programmer (not
more, no less), but I hope he learns/tries to learn it deeper. That's
OK, on every forum there're some guys who learned some technology a
bit deeper and after that start talk (in general with newbies as it
easiest way) in perfect manner from the top ;) On what I always remind
- remember - the top is always relative, so don't speak with anybody
from the top. Or, try to speak in such manner with those who know it
better. As usually, the conclusion will be: aggression, total negation
(sure, or everybody will see that you're not on top :D), attempts to
find a way out and the justification of the told nonsense (even this
attempts is already not about technology ;)) and so on.

But as I've also mentioned, such discussions are not professional
discussions. The main goal of the professional discussion is to find
the truth, but not the desire to win the "dispute" or fear to lose it.
The professional discussion is always *discussion* but not the
amateurish dispute.

Lasse Reichstein Nielsen

unread,
Nov 24, 2009, 12:13:56 PM11/24/09
to
"Dmitry A. Soshnikov" <dmitry.s...@gmail.com> writes:

> In fact, even guessing about implementation, that is already nonsense,
> as there's no any element created (that's in ES) and no need to
> allocated some pointers.

And yet, it happens.
Try executing

var res = [];
window.rooted_storage = res; // Make sure it's not GC'ed.
for (var i = 0 ; i < 10000; i++) {
res.push(new Array(50000));
}

in different browsers and see how they fare. After all, 10000 small
objects should be well within their capability, but if the arrays are
not sparse, we are talking multi-gigabyte allocation here.

My experience is:
Safari 4 and Chrome 4: Allocates like mad (if you keep clicking "Continue"
in Safari)
Opera 10 and Firefox 3.5: Finishes immediately.
IE: I didn't dare. I need to use the machine again today :)

>> In any case, the initial array would not store
>> objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
>> 8.1).
>
> Also wrong, there's no any value (not even `undefined`), so learn ES
> deeper, then will talk in manner in which you're trying ;)

The underlying array, which *is* allocated in some browsers,
necessarily holds some value. It's probably not "undefined", though,
as that would be indistinguishable from an actual value.

Jorge

unread,
Nov 24, 2009, 1:31:09 PM11/24/09
to
On Nov 24, 6:13 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com> writes:
>
> > In fact, even guessing about implementation, that is already nonsense,
> > as there's no any element created (that's in ES) and no need to
> > allocated some pointers.
>
> And yet, it happens.
> Try executing
>
>  var res = [];
>  window.rooted_storage = res;  // Make sure it's not GC'ed.
>  for (var i = 0 ; i < 10000; i++) {
>    res.push(new Array(50000));
>  }
>
> in different browsers and see how they fare.  After all, 10000 small
> objects should be well within their capability, but if the arrays are
> not sparse, we are talking multi-gigabyte allocation here.

Yes, the creation of an empty array object takes some memory for the
structures of the array object itself have to be allocated somewhere
for it to exist.

But the *elements* of said empty array (like in new Array(8e6)[3e6])
do not, not at all, not even a single byte.

> My experience is:
> Safari 4 and Chrome 4: Allocates like mad (if you keep clicking "Continue"
>  in Safari)
> Opera 10 and Firefox 3.5: Finishes immediately.
> IE: I didn't dare. I need to use the machine again today :)
>
> >> In any case, the initial array would not store
> >> objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
> >> 8.1).
>
> > Also wrong, there's no any value (not even `undefined`), so learn ES
> > deeper, then will talk in manner in which you're trying ;)
>
> The underlying array, which *is* allocated in some browsers,
> necessarily holds some value. It's probably not "undefined", though,
> as that would be indistinguishable from an actual value.

No no no.

Given a= new Array(8e6);

The element a[anyElement] occupies no memory and holds no value, not
until something (whatever) is assigned to it. That the array object
"a" returns "undefined" when indexed with [3e6] or for any non-
existing elements does not mean that non-existing elements exist and
hold the value undefined.

If non-existing elements required even a *single* bit (!), that would
mean that an empty array object with 2^32 elements (like in a=new Array
(2^32-1)) would allocate (2^32)/8/1024/1024 === 512Mb === 0.5 GB,
which obviously is not the case as you can easily see by executing
this and watching memory allocation:

//Lets go for 8 GigaBytes:

var l, a, e, n;
l= Math.pow(2, 32)-1;
a= [];
n= 2*8;
while (n--) {
a.push(e= new Array(l));
console.log(n+ ":"+ e.length);
}
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 24, 2009, 2:04:04 PM11/24/09
to
On Nov 24, 8:13 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com> writes:
>
> > In fact, even guessing about implementation, that is already nonsense,
> > as there's no any element created (that's in ES) and no need to
> > allocated some pointers.
>
> And yet, it happens.
> Try executing
>
>  var res = [];
>  window.rooted_storage = res;  // Make sure it's not GC'ed.
>  for (var i = 0 ; i < 10000; i++) {
>    res.push(new Array(50000));
>  }
>
> in different browsers and see how they fare.  After all, 10000 small
> objects should be well within their capability, but if the arrays are
> not sparse, we are talking multi-gigabyte allocation here.
>
> My experience is:
> Safari 4 and Chrome 4: Allocates like mad (if you keep clicking "Continue"
>  in Safari)
> Opera 10 and Firefox 3.5: Finishes immediately.
> IE: I didn't dare. I need to use the machine again today :)
>

Yeah, thanks Lasse, seems Chrome and Safari are really irrelevant in
this case (15.4.2.2) and for them it's not a nonsense. That's useful
information. Moreover, it doesn't depends on modification of
the`length` property, e.g.:

for (var i = 0 ; i < 10000; i++) {

a = [];
a.length = 50000;
res.push(a); // it's OK in Chrome and Safari also
}

But I've analyzed the sources of V8 and disappoint with it (if
interesting, see file `heap.h`, line 449, there's method prototype):

// Allocates a fixed array initialized with the hole values.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
// failed.
// Please note this does not perform a garbage collection.
static Object* AllocateFixedArrayWithHoles(int length);

`AllocateFixedArrayWithHoles` - sounds funny, the "fatest" (as they
say) browser has such strange non-conformant implementation for arrays
that should be sparse.

> >> In any case, the initial array would not store
> >> objects, but `undefined' values, of the primitive `Undefined' type (ES3F,
> >> 8.1).
>
> > Also wrong, there's no any value (not even `undefined`), so learn ES
> > deeper, then will talk in manner in which you're trying ;)
>
> The underlying array, which *is* allocated in some browsers,
> necessarily holds some value. It's probably not "undefined", though,
> as that would be indistinguishable from an actual value.
>

Yes, they fill values with the `holes` (as they called them). Pointer
that or not it doesn't matter in this case, as values are there.

Thanks again for making test.

Dmitry A. Soshnikov

unread,
Nov 24, 2009, 2:18:25 PM11/24/09
to
On Nov 24, 9:31 pm, Jorge <jo...@jorgechamorro.com> wrote:

[...]

>


> No no no.
>
> Given a= new Array(8e6);
>
> The element a[anyElement] occupies no memory and holds no value, not
> until something (whatever) is assigned to it. That the array object
> "a" returns "undefined" when indexed with [3e6] or for any non-
> existing elements does not mean that non-existing elements exist and
> hold the value undefined.
>
> If non-existing elements required even a *single* bit (!), that would
> mean that an empty array object with 2^32 elements (like in a=new Array
> (2^32-1)) would allocate (2^32)/8/1024/1024 === 512Mb === 0.5 GB,
> which obviously is not the case as you can easily see by executing
> this and watching memory allocation:
>
> //Lets go for 8 GigaBytes:
>
> var l, a, e, n;
> l= Math.pow(2, 32)-1;
> a= [];
> n= 2*8;
> while (n--) {
>   a.push(e= new Array(l));
>   console.log(n+ ":"+ e.length);}
>
> --
> Jorge.

I see that V8 has check for the incoming `length`. So, in your case:
`l= Math.pow(2, 32)-1;` it's too big number to use their
`AllocateFixedArrayWithHoles`, but if to use some "real" number `l=
50000`, you'll see memory issue. Even Chrome says it itself in toolbar
above.

Dmitry A. Soshnikov

unread,
Nov 24, 2009, 3:16:10 PM11/24/09
to
I've checked the V8 sources more deeply, and found out that the main
whole chain:

BUILTIN(ArrayCode) -> array->SetElementsLength(...) -> :

// General slow case.
if (len->IsNumber()) {
uint32_t length;
if (Array::IndexFromObject(len, &length)) {
return SetSlowElements(len);
} else {
return ArrayLengthRangeError();
}
}

-> SetSlowElements(...) -> :

Object* obj = NormalizeElements();
if (obj->IsFailure()) return obj;

// Update length for JSArrays.
if (IsJSArray()) JSArray::cast(this)->set_length(len);

-> NormalizeElements(...) -> :

Object* obj = NumberDictionary::Allocate(length); // that's it
if (obj->IsFailure()) return obj;

failure in here means a too big number (like in Jorge's example).
After that there's cycle in elements which should be updated if they
are not holes, but it's no interesting in our case as all of them are
holes:

// Copy entries.
for (int i = 0; i < length; i++) {
Object* value = array->get(i);
if (!value->IsTheHole()) {
...
}
}

So, for Chrome (V8), the main things is in line: `Object* obj =
NumberDictionary::Allocate(length);`. That's really interesting info,
but in my opinion not useful implementation.

P.S.: Thomas 'PointedEars' Lahn, but don't even thinks that's about
you ;), it's about Lasse.

Stefan Weiss

unread,
Nov 24, 2009, 5:10:45 PM11/24/09
to
On 24/11/09 21:16, Dmitry A. Soshnikov wrote:
> I've checked the V8 sources more deeply, and found out that the main
> whole chain:
>
> BUILTIN(ArrayCode) -> array->SetElementsLength(...) -> :
>
> // General slow case.
> if (len->IsNumber()) {
> uint32_t length;
> if (Array::IndexFromObject(len, &length)) {
> return SetSlowElements(len);
> } else {
> return ArrayLengthRangeError();
> }
> }
>
> -> SetSlowElements(...) -> :
>
> Object* obj = NormalizeElements();
> if (obj->IsFailure()) return obj;
>
> // Update length for JSArrays.
> if (IsJSArray()) JSArray::cast(this)->set_length(len);
>
> -> NormalizeElements(...) -> :
>
> Object* obj = NumberDictionary::Allocate(length); // that's it
> if (obj->IsFailure()) return obj;
>
> failure in here means a too big number (like in Jorge's example).

[snip]

> So, for Chrome (V8), the main things is in line: `Object* obj =
> NumberDictionary::Allocate(length);`.

If I'm not mistaken, this is the part where they decide if the requested
array length is "too long" to pre-allocate memory for the new array's
elements:

int size = FixedArray::SizeFor(length);
return size <= kMaxObjectSizeInNewSpace
? new_space_.AllocateRaw(size)
: lo_space_->AllocateRawFixedArray(size);

<http://code.google.com/p/v8/source/browse/trunk/src/heap.cc#2801>

kMaxObjectSizeInNewSpace is defined in heap.h; it depends on the target
architecture:

#if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB;
#else
static const int kMaxObjectSizeInNewSpace = 256*KB;
#endif

<http://code.google.com/p/v8/source/browse/trunk/src/heap.h#915>

> That's really interesting info,
> but in my opinion not useful implementation.

Why not? Sounds reasonable, if the cutoff value is chosen carefully.
Allocating memory is typically a lot more expensive than copying/moving
values around; this looks like a pretty useful optimization to me.


cheers,
stefan

Dmitry A. Soshnikov

unread,
Nov 25, 2009, 3:50:38 AM11/25/09
to

Yes, thanks, I saw it also yesterday, and after that (my previous last
comment) showed the code-chain how `Array(len)` is handled, it's about
`Object* obj = NumberDictionary::Allocate(length);`. And also saw
`kMaxObjectSizeInNewSpace`, about 512Mb exactly I have in used when
Chrome showed it's toolbar about that script eats much memory
(meanwhile, I have Win32, but 64-bits processor, so maybe
`V8_TARGET_ARCH_X64` means 64-processor, but 64-OS).


> > That's really interesting info,
> > but in my opinion not useful implementation.
>
> Why not? Sounds reasonable, if the cutoff value is chosen carefully.
> Allocating memory is typically a lot more expensive than copying/moving
> values around; this looks like a pretty useful optimization to me.
>

Maybe, but not sure, because "laze instantiation" is the way for do
not suggest to user whole the stuff at once, forcing him to wait for a
while. Even if by parts in summary it should take more time. If to
note that arrays in ES are sparse (by definition) and should not
different from other objects (beside some algorithm), such
optimization seems a "little bit" strange. If it is so, why didn't
they do the same on `length` modification in case of `var a = [];
a.length = 50000;`?

I saw in code, that they have general implementation for several kinds
of arrays: internal arrays, JSArrays, PixelArrays (for Canvas) and
maybe something else. So I think this "optimization" for `Array(50000)
` is just consequence of that implementation. But it just my opinion.

Anyway, what I can say precisely is that Chrome (V8) taking ideas and
code of Safari (WebKit, JavaScriptCore) also has taken Safari's
"optimization" - that irrelevant with 15.4.2.2 ES-3 mistake. They
shouldn't do so (let's start from this). But sure they can do so as
it's just implementation of technical specification.

About "lazy instantiation" sure the decision to use it or not should
be made by analysis of the current system. In some case it useful to
load full data, in some - not: you won't force user to wait while all
of your system will be loaded, right? If you have 50000 modules and
user usually uses only 10 of them, you won't do so, yep? That's it. So
it depends on the system. And in this case Chrome which has inherited
implementation errors from WebKit, is wrong - because we see the
result - that script uses much memory.

/ds

Jorge

unread,
Nov 25, 2009, 6:03:32 AM11/25/09
to
On Nov 24, 8:04 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:

OMG...

Dmitry, my dear comrade :-), what should we do now that Pointy was
perfectly right ?
To duck and run or to apologize ???

Ahem... sorry Pointy, you're still the best :-)
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 25, 2009, 8:36:16 AM11/25/09
to

It doesn't matter, as I mentioned that professional discussion - is
professional discussion. And this discussion was with Lasse in this
case (regarding to this issue), not with Thomas 'PointedEars' Lahn.
Although, Thomas 'PointedEars' Lahn becomes right he didn't know it
himself how it's exactly (as he said: "only to the possibilities for
an implementation", in other words - guessing about that, but even try
to make a test, as we didn't so). Moreover, he's still was wrong about


"In any case, the initial array would not store objects, but

`undefined' values, of the primitive `Undefined' type (ES3F, 8.1)",
which is regarding to *exactly specification* but not guessing about
implementation. The last point is still nonsense. So, Thomas
'PointedEars' Lahn is was right in one moment (he guessed, just
lucky), but with wrong reason. And was not right when saying about
`undefined` values referencing to the specification.

As for me, I'm interesting in information and conversations with the
main goal - to find the truth. We've found the truth, Chrome repeats
after Safari - and both are wrong regarding to specification. I agree
with that, and this is valuable info for me. If someone is interested
in the same way - I'm always glad to have a talk, discussion. Thomas
'PointedEars' Lahn is not exception in this case, but, repeat, only
with the professional goal - to find the truth ;)

Jorge

unread,
Nov 25, 2009, 8:58:44 AM11/25/09
to
On Nov 24, 11:10 pm, Stefan Weiss <krewech...@gmail.com> wrote:
> (...)

> Why not? Sounds reasonable, if the cutoff value is chosen carefully.
> Allocating memory is typically a lot more expensive than copying/moving
> values around; this looks like a pretty useful optimization to me.

Where it's done, and when it's done, yes:

Safari 4.0.4 : up to 4x faster (!)
Safari 3.2.3 : up to 2x faster
Chrome 4.0.249.12: up to 2x faster
FireFox 3.6b3 : up to 2x faster
FireFox 3.5.4 : no speedup
FireFox 3.0.15 : no speedup
FireFox 2.0.0.20 : no speedup
Opera 10.10 : no speedup, but Opera is the 2nd fastest (after
Safari 4).
NN7 : no speedup.
NN9 : no speedup.

(Mac versions)

The test code is at:
http://jorgechamorro.com/cljs/086/index.html
--
Jorge.

Jorge

unread,
Nov 25, 2009, 9:12:11 AM11/25/09
to
On Nov 25, 2:36 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:
> (...)

I see your point, yes, and I agree. But while my tests were showing
the opposite of what he said I ended up saying maybe a pair of things
too much, and in the end he was right, we have to admit.

Did you see my other post with the tests ?
Cheers,
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 25, 2009, 9:37:17 AM11/25/09
to

Yeah, thanks, good tests, the performance is better I guess that no
`length` property modification is taken place. Meanwhile, in Firefox
3.5.5 where's no speedup seems they analyzes `length` every time, but
what about v.3.6, the make optimization by not analyzing `length` if
it's greater? Have to see sources. Btw, one more test is would be
useful: `var a = []; a.length = 20000;` and last iteration is
interesting (especially in Safari) - it should be the fastest - as
there should be no any allocation and no `length` analysis should
taken place (but, it's only guess, if it's not hard, please add this
test also to this page, maybe I'll recommend this test page on other
forums).

Dmitry A. Soshnikov

unread,
Nov 25, 2009, 9:45:46 AM11/25/09
to
On Nov 25, 5:12 pm, Jorge <jo...@jorgechamorro.com> wrote:
> On Nov 25, 2:36 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
> wrote:
>
> > (...)
>
> and in the end he was right, we have to admit.
>

Jorge, nobody said that Thomas 'PointedEars' Lahn wasn't right in
exactly guessing about implementations, I said, he was right but with
the wrong reason, also was wrong about `undefined` values referencing
to the specification. But I repeat that all doesn't matter, as only
one thing is essential - finding the truth, that's the professional
discussion ;) I'm opened to such discussions, with everyone (with you,
Lasse or Thomas 'PointedEars' Lahn, or anybody else interesting in
ES). The truth information is essential, but not the amateurish
disputes. If I get correct information in discussion, sure I'll be
grateful for it and will say that I was wrong. This is now, but
regarding to Lasse.

Jorge

unread,
Nov 25, 2009, 9:48:51 AM11/25/09
to
On Nov 25, 3:37 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:
> (...) Btw, one more test is would be

> useful: `var a = []; a.length = 20000;` and last iteration is
> interesting (especially in Safari) - it should be the fastest - as
> there should be no any allocation and no `length` analysis should
> taken place (but, it's only guess, if it's not hard, please add this
> test also to this page

[x] Done.
--
Jorge.

Dmitry A. Soshnikov

unread,
Nov 25, 2009, 10:00:37 AM11/25/09
to

Thanks, funny results:

a= new Array(200000), filling 200000 items, up to item
[199999]............ 89 ms
a= new Array(200000), filling 200000 items, up to item
[199999]............ 89 ms
a= new Array(200000), filling 200000 items, up to item
[199999]............ 89 ms
Average (3
loops)......................................................... 89 ms
.
a= []; a.length= 200000; a;, filling 200000 items, up to item
[199999]..... 329 ms
a= []; a.length= 200000; a;, filling 200000 items, up to item
[199999]..... 321 ms
a= []; a.length= 200000; a;, filling 200000 items, up to item
[199999]..... 320 ms
Average (3
loops)......................................................... 323.33
ms

Yep, allocation and filling with `holes` in Safari is fastest variant,
I recognize it and agree with that. This is non-comformant to
specification but optimization - if cutoff value is chosen carefully
as mentioned Stefan. Even if there's no `length` analysis and
modification, seems allocation for each element is more expensive by
time resources.

Btw, it's not related to Chrome (meanwhile is fairly for Safari) -
there results are nearly the same, I have Chrome version 3.0.159.33,
WinXp, even new Array(200000) slower than first and the last tests.

Jorge

unread,
Nov 25, 2009, 11:17:30 AM11/25/09
to
On Nov 25, 4:00 pm, "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com>
wrote:
> (...)

> Btw, it's not related to Chrome (meanwhile is fairly for Safari) -
> there results are nearly the same, I have Chrome version 3.0.159.33,
> WinXp, even new Array(200000) slower than first and the last tests.

Ooops, yes, you're right. Chrome is a "no speedup":

Safari 4.0.4 : up to 4x faster (!)
Safari 3.2.3 : up to 2x faster

FireFox 3.6b3 : up to 2x faster

Chrome 4.0.249.12: no speedup


FireFox 3.5.4 : no speedup
FireFox 3.0.15 : no speedup
FireFox 2.0.0.20 : no speedup

Opera 10.10 : no speedup, but it's 2nd fastest after Safari 4.
NN7 : no speedup
NN9 : no speedup

(Mac/OSX/10.6.2)
http://jorgechamorro.com/cljs/086/index.html
--
Jorge

Lasse Reichstein Nielsen

unread,
Nov 26, 2009, 1:02:07 AM11/26/09
to
"Dmitry A. Soshnikov" <dmitry.s...@gmail.com> writes:

[Allocating a dense backing array for new Array(50000)]

> This is non-comformant to specification but optimization - if cutoff
> value is chosen carefully as mentioned Stefan.

Just to be precise: This implementation is fully conformant with the
specification. The array behaves, in all *specified* ways, exactly as
creating an empty array and setting its length to 50000.

The only thing that differs is the internal representation and the
time/memory behavior, neither of which are covered by the
specification.

Dmitry A. Soshnikov

unread,
Nov 26, 2009, 3:34:26 AM11/26/09
to
On Nov 26, 9:02 am, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> "Dmitry A. Soshnikov" <dmitry.soshni...@gmail.com> writes:
>
> [Allocating a dense backing array for new Array(50000)]
>
> > This is non-comformant to specification but optimization - if cutoff
> > value is chosen carefully as mentioned Stefan.
>
> Just to be precise: This implementation is fully conformant with the
> specification. The array behaves, in all *specified* ways, exactly as
> creating an empty array and setting its length to 50000.
>

Yep, from the point of view in ES it's conforming, we have empty array
with passed length.

> The only thing that differs is the internal representation and the
> time/memory behavior, neither of which are covered by the
> specification.
>

I meant this situation, but as I mentioned above, it's implementation
and they can do that. And actually, this also true, although they have
cycle `for ... < length` analyzing `holes`. Non-conforming from point
of view that they *do* something with elements regardless that
elements are internal. It's sort of if written: "don't do anything
with elements, moreover, don't created any elements, only set the
length", on what they say: "we don't create any JS-elements, but
that's out deal to do everything with internal `hole`-elements with
allocating memory for the optimization and cycling this array up to
the length". So, this is conformant from the ES, but concrete
situation with big length such as Array(50000), when browser dies and
asks to reload it, forces to think that something they have done
"wrong", but as we've seen - not wrong from their point of view, but
in some places even better from the optimization point of view. And
moreover, in Chrome there's no optimization like there's in Safari,
but, that's also just Chrome's implementation own issue.

0 new messages