Closed
Bug 638414
Opened 13 years ago
Closed 13 years ago
Missing toString() function on Array.prototype - TypeError: Array.prototype.toString called on incompatible Object
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: terje.rosenlund, Unassigned)
Details
Attachments
(1 file)
256 bytes,
text/plain
|
Details |
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; nb-NO; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14 Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 6.1; nb-NO; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14 trx.mirrorClone = function trx_mirrorClone(obj) { function Clone() { } Clone.prototype = obj; return new Clone(); } a = [1,2,3]; b = trx.mirrorClone(a); Obj.0 = 1 Obj.1 = 2 Obj.2 = 3 c = [a, b]; Obj.0 = 1,2,3 Obj.1 = undefined The same code in IE gives: Obj.0 = 1,2,3 Obj.1 = 1,2,3 Seems like ff allowes such a cloned object to be assigned to a var but not to an object- or array- member Reproducible: Always
Reporter | ||
Updated•13 years ago
|
Version: unspecified → 1.9.2 Branch
Comment 1•13 years ago
|
||
> Obj.1 = undefined
How did you determine that, exactly?
When I run the above in a 1.9.2 build and try to print out c[1], I get:
TypeError: Array.prototype.toString called on incompatible Object
On trunk I get the sort of output you'd sorta expect (though calling Array.prototype.toString on a non-array shouldn't make you expect too much...)
Comment 2•13 years ago
|
||
Reporter | ||
Comment 3•13 years ago
|
||
> How did you determine that, exactly? I have a dump(anything) function and the cause for 'undefined' was something like: var v; var s; for (var i in c) { try { val = c[i]; } catch(e) { val = e.message; } s + = 'Obj.' + i + ' = ' + v + '\n'; } s; My dump() function can be allowed to go deeper in objects and then I can se that the values are actually there: Obj.0 = 1,2,3 Obj.0.0 = 1 Obj.0.1 = 2 Obj.0.2 = 3 Obj.1 = undefined Obj.1.0 = 1 Obj.1.1 = 2 Obj.1.2 = 3 Obj.1 = undefined is still there and is very misleding so I have changed my dump() to: try { v = v.toString(); } catch (e) { v = trx.constructor(v) ? '[' + typeof v + ' ' + trx.typeof(v) + ']' : e.message; } Then: a = [1,2,3]; b = trx.mirrorClone(a); c = [a, b] Obj.0 = 1,2,3 Obj.1 = [object Array] And that solved the mystery why I had to do the try/catch in the first place (years from now) > On trunk I get the sort of output you'd sorta expect (though calling > Array.prototype.toString on a non-array shouldn't make you expect too much...) I have read that all objects should have a toString() function attached so even the String object has it. It's no less needed for prototypes I guess so that the problem no longer exists in trunk is good news The subject on this case became very misleading so I have changed it (Objects created from another objects prototype can't be assigend to an object- or array- member) I pressume this case should be closed as INVALID or maybe a dup? (the reason for change in trunk)
Summary: Objects created from another objects prototype can't be assigend to an object- or array- member → Missing toString() function on Array.prototype - TypeError: Array.prototype.toString called on incompatible Object
Comment 4•13 years ago
|
||
There _is_ a toString on Array.prototype in 1.9.2. It just throws if you call it on a non-Array object. ;) This looks like worksforme, in any case. If someone wants to find the bug where the change to Array.prototype.toString was made, they should feel free to change the resolution to duplicate, of course!
Status: UNCONFIRMED → RESOLVED
Closed: 13 years ago
Resolution: --- → WORKSFORME
Reporter | ||
Comment 5•13 years ago
|
||
Ok, seems like I don't have grasped the full consept of prototypes then? I named this function mirrorcClone() because objects created by it acts different than what normaly could be called a clone. The differense is that it containes a relationsheep with the object its created from (master). Values from the master shines through on all objects created from the master until you assign values to the local copy(s). Deleting a local value makes the master value show up again. A change on a value in the master is reflected in all objects not having their local copy set. This makes it possible to create objects from a master object and use one or more values in it to inform all cloned objects by changing value(s) in the master. This looks like pointers in C to me (pointers to vars in a pointer to a struct) and I have guessed that eg. a cloned array has pointers to its master array AND all its members as default. Pointers may be changed to point to localy allocated space for vars and the array itself. Deleting a local value makes its pointer to fall back on its master. Therefore my object is not an array but a pointer to an array and must be dereferenced to be accessed. Dereferencing is normaly done by javascript itself but clearly not in this case In the past I have not been able to create an equivalent to pointers to vars in C but this approach makes it possible and gives me very powerfull new possibilities in javascript I might have misunderstood this consept and would realy appreciate a correction if so
Comment 6•13 years ago
|
||
> Therefore my object is not an array but a pointer to an array and must be
> dereferenced to be accessed.
Not quite. Your object is just an object. Property lookups on it will look for properties on the prototype chain, though.
So if you have an object X whose prototype is an array A, then looking up toString on X will look on X, then on A, then on the prototype of A, and find it there. The function it will find is Array.prototype.toString.
Then you call the function, with the |this| object set to X. This is the same as doing this:
Array.prototype.toString.call(X);
What that does depends on what the spec says. The spec for Array.prototype.toString (ECMA-262 edition 5 section 15.4.4.2) is:
1. Let 'array' be the result of calling ToObject on the |this| value.
2. Let 'func' be the result of calling the [[Get]] internal method of
'array' with argument "join".
3. If IsCallable(func) is false, then let 'func' be the standard
built-in method Object.prototype.toString (15.2.4.2).
4. Return the result of calling the [[Call]] internal method of 'func'
providing 'array' as the this value and an empty arguments list.
Reporter | ||
Comment 7•13 years ago
|
||
So Let 'array' be the result of calling ToObject on the |this| value has been changed in trunk then Always a pleasure to be wrong when you are answering my requests - Thank you!
Comment 8•13 years ago
|
||
> So Let 'array' be the result of calling ToObject on the |this| value has been
> changed in trunk then
No, that part hasn't changed. Something after that has, presumably.
Comment 9•13 years ago
|
||
Array.prototype.toString used to not be generic -- it would throw if called on anything but an Array. ES5 changed that to be generic to anything by delegating behavior to a "join" property if one was present. We implemented that change in bug 562446.
Reporter | ||
Comment 11•13 years ago
|
||
(In reply to comment #9) > Array.prototype.toString used to not be generic - Was there any generic toString() function in 1.9.2.14 at all? (if so I may override default Array.prototype.toString(?)) - When will this fix be in a release?
Comment 12•13 years ago
|
||
> - Was there any generic toString() function in 1.9.2.14 at all? Object.prototype.toString. > - When will this fix be in a release? When Firefox 4 shops. Figure a few weeks at most.
Reporter | ||
Comment 13•13 years ago
|
||
In my root script: Array.constructor.prototype.toString = Object.constructor.prototype.toString; Works!
Reporter | ||
Comment 14•13 years ago
|
||
Does'nt that mean that the fix in trunk could be simply to delete the Array.constructor.prototype.toString() function ? Should cause Array to use first toString() found in prototype-chain = Object.toString() (?)
Comment 15•13 years ago
|
||
I'm not sure what comment 14 is asking.
Reporter | ||
Comment 16•13 years ago
|
||
ES5 15.2.4 Properties of the Object Prototype Object The value of the [[Prototype]] internal property of the Object prototype object is null ES5 15.4.4: The value of the [[Prototype]] internal property of the Array prototype object is the standard built-in Object prototype object (15.2.4). Array is derived from Object so a missing toString() function in Array would cause a lookup in the prototype-chain and find it in Object?
Comment 17•13 years ago
|
||
Yes.
Reporter | ||
Comment 18•13 years ago
|
||
Mid-air collision! Posts anyway but no need for answer:) Changed my root script from: Array.constructor.prototype.toString = Object.constructor.prototype.toString; to: delete Array.prototype.toString; Both eliminates TypeError: Array.prototype.toString called on incompatible Object and confirms my assumption
You need to log in
before you can comment on or make changes to this bug.
Description
•