Page 1 of 1

User properties Array not correctly got

Posted: 17 Jul 2011, 14:29
by rjgtav
Hi. The bug is that when you put an Array (array of objects in my case) in the user properties (by using user.properties.put("array", myArray), it puts the array correctly, but when i get it later (by using user.properties.get("array"), the array loses some of its properties.

In my case I was trying to concatenate one of the user properties (to get a new array and not update the one inside the properties) but, after looping through the concatenated array, i got an unexpected result, all of the content of the array from the properties was added to the first index to the concatenated array.

Here's an example code:

Code: Select all

var array1 = [1, 2, 3, 4];
user.properties.put("array", array1);

var array2 = user.properties.get("array").concat();

trace("=== Array1 ===")
trace("length: "+array1.length)
for(var i = 0; i<array1.length; i++){
    trace(i+": "+array1[i]);
}

trace("=== Array2 ===")
trace("length: "+array2.length)
for(var i = 0; i<array2.length; i++){
    trace(i+": "+array2[i]);
}
And here's the output:
=== Array1 ===
length: 4
0: 1
1: 2
2: 3
3: 4
=== Array2 ===
length: 1
0: 1, 2, 3, 4
As you can see, in this case the concat() function copies all the properties array to the first index of the new array.

Despite this, so far, all the other array's properties work, such as length, and looping through it works fine. I haven't tested the other Array's methods like splice, sort, etc.

As a temporary solution, i had to create a function that creates a new array from the properties one, by looping through it.

[EDIT]
Forgot to mention that the concat() function works in arrays created on server-side, only doesn't work on arrays inside the user properties.

Best regards,
rjgtav

Notes:
I'm using SFS Pro 1.6.9

Posted: 18 Jul 2011, 01:06
by BigFIsh
Have you tried casting the property as Array before calling 'concat()' method?

i.e. (user.properties.get("array") as Array).concat() or Array((user.properties.get("array")).concat() ?

The properties are stored as 'lose type' (meaning, it can be anything). Actionscript may even mistake it for a string, since there's a String.Concat() method.

Posted: 18 Jul 2011, 08:12
by rjgtav
hi. Yes i tried casting it to Array but nothing changed. Sorry, i forgot to mention it.

Posted: 19 Jul 2011, 20:13
by rjgtav
Could anyone please confirm if this is really a bug?

Thanks

Posted: 19 Jul 2011, 23:23
by BigFIsh
I just ran your script with an actionscript extension and this is what I got from the output window:
[sfsExtension.as]: === Array1 ===
[sfsExtension.as]: length: 4
[sfsExtension.as]: 0: 1
[sfsExtension.as]: 1: 2
[sfsExtension.as]: 2: 3
[sfsExtension.as]: 3: 4
[sfsExtension.as]: === Array2 ===
[sfsExtension.as]: length: 4
[sfsExtension.as]: 0: 1
[sfsExtension.as]: 1: 2
[sfsExtension.as]: 2: 3
[sfsExtension.as]: 3: 4
What SFS version are you using?

Posted: 20 Jul 2011, 09:28
by rjgtav
Hi. I'm using SFS PRO 1.6.9.

Curiously that code (that i wrote on mobile) works ok and even in an extension it works, but, in a project i'm doing, where the array is set at the beggining and only got some time later, this bug happens.

I'll try to prepare a reproducible test case.

Posted: 20 Jul 2011, 10:09
by rjgtav
Hi again. After lots of testing, i've finally managed to create a reproducible test case.
First, this is the weirdest and hardest to catch bug i've ever seen, as it only happens in a specific test case.

For it to happen, you need to create the array in one extension, and try to get it and apply the concat() method in another extension. If it is in the same extension, the bug won't occur.

So, for this, i created 2 simple extensions:

ArrayTest.as

Code: Select all

function init(){}
function destroy() {}
function handleInternalEvent(evt){}

function handleRequest(cmd, params, user, fromRoom)
{
	if(cmd == "prepareArray"){
		var array1 = [1, 2, 3, 4];
		
		trace("=== Array1 ===") 
		trace("length: "+array1.length) 
		for(var i = 0; i<array1.length; i++){ 
		    trace(i+": "+array1[i]); 
		}
		
		user.properties.put("array", array1);
	}
}
ArrayTest2.as

Code: Select all

function init(){}
function destroy(){}
function handleInternalEvent(evt){}

function handleRequest(cmd, params, user, fromRoom)
{
	if(cmd == "getArray"){
		var array2 = user.properties.get("array").concat();
		
		trace("=== Array2 ===") 
		trace("length: "+array2.length) 
		for(var i = 0; i<array2.length; i++){ 
		    trace(i+": "+array2[i]); 
		}
	}
}
And here's the output:
=== Array1 ===
length: 4
0: 1
1: 2
2: 3
3: 4
=== Array2 ===
length: 1
0: 1, 2, 3, 4
Hope this helps finding it ;-)

Important Notes:
- I'm using SFS PRO 1.6.9 on a Windows 7 32 bit Laptop
- The array1 can be an array with any kind of data inside. Tested with Numbers, Strings, Objects and Arrays and the bug always happens
- The array1 can have any length (greater than 1) to see the bug happening (tested with both odd and even length);
- As mentioned earlier, if I execute the concat() on the ArrayTest.as extension (the same where i created the array1), even putting in the properties and then getting it, the bug doesn't happen

Posted: 21 Jul 2011, 21:52
by rjgtav
hi bigfish, could you please test this and confirm if this is a bug?
Thanks

Posted: 21 Jul 2011, 23:31
by BigFIsh
I just tested this and I can confirm it's a bug - and it's a strange one! :shock:

It does seem related to concat() function with multiple AS extensions. If no concat() was used, the values of the array will be traced out correctly.

So, as a workaround - use slice() function. It'll do what you want - duplicating an array.

Nice find :)

However, it's quite unlikely this will get fixed. Actionscript extension is prehistoric.

This also gives another good reason (to a list of reasons) why a single zone extension to do everything is a must.

Posted: 22 Jul 2011, 08:40
by rjgtav
hi. Thanks for confirming this. Yeah i know its better a single extension, but in my case i really need multiple extensions accessing this array (its for an inventory system). Once again, thanks :-)