Closed Bug 253138 Opened 20 years ago Closed 11 years ago

Array.prototype.toSource excludes non-indexed enumerable properties

Categories

(Core :: JavaScript Engine, defect, P3)

x86
Windows XP
defect

Tracking

()

RESOLVED WONTFIX
mozilla1.9alpha1

People

(Reporter: timeless, Unassigned)

Details

> a=[1,2,3];a.b=1; a.toString();
1,2,3
> uneval(a);
[1, 2, 3]

i'd like access to b, and from talking w/ brendan+shaver that i should get it
-> default qa
QA Contact: pschwartau → general
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: -- → P5
With ECMA TG1 back in action, there is a chance we could do this.  Way back in
'98 (IIRC), MS balked at standardizing anything because of serialization hard
cases, which their rep argued made it all too domain-specific for a standard
method set to help much.  That's overstating the case, and the proof is JSON
(used by gmail and other "AJAX" [glug] apps).

What does JSON do for this case?

/be
Actually, JSON appears to just go through the items numerically (from 0 to
length-1) and create a [item0, item1, item2, ...] construct, according to the
code at http://www.crockford.com/JSON/json.js - is that what you were refering to?
(In reply to comment #3)
> Actually, JSON appears to just go through the items numerically (from 0 to
> length-1) and create a [item0, item1, item2, ...] construct, according to the
> code at http://www.crockford.com/JSON/json.js - is that what you were refering
> to?

Yes, that's it -- thanks.

When I did toSource and uneval years ago, I thought about making it possible to
add ad-hoc properties to an Array instance, and round-trip those properties via
uneval | eval.  The thought was to generalize object literal notation to allow
the class of the object to be specified.  Something like:

var a = {#class: Array, 0: 1, 1: 2, 2: 3, b: 1};

The #class name was a straw-man, based on sharp variables and not wanting to use
yet another reserved character.  The potential drawback (for implementors) or
feature (for users) here is that #class looks like any other initializer, and
could be in any order.  An alternative that hoists it out might look like:

var a = #class=Array{0: 1, ...};

or even just:

var a = #Array{0: 1, ...};

Thoughts welcome.

/be

(In reply to comment #4)

> or even just:
> 
> var a = #Array{0: 1, ...};

Or *even* something without ugly new characters:

var a = new Array {0: 1, 1: 2, 2: 3, b: 1};

It's prettier.

/be
(In reply to comment #5)
> var a = new Array {0: 1, 1: 2, 2: 3, b: 1};

That's actually pretty elegant, and clean to look at IMHO (though not very
effecient for the array props, but I doubt you can solve that while dealing with
generic classes and properties).

My only questions are, where would constructor parameters go, and would the prop
initialisation occur before or after the constructor is called? I'm not sure
which way around I'd prefer for either question...
(In reply to comment #6)
> My only questions are, where would constructor parameters go, and would the prop
> initialisation occur before or after the constructor is called? I'm not sure
> which way around I'd prefer for either question...

This was where the MS guy at ECMA TG1 in '98 started saying "it's too hard", and
he had other hard cases.

To make this work, it has to be so simple that it won't cover all cases, but it
will be easy to remember for most JS hackers.  I think the constructor must be
called first, then the properties set (as if by assignment).  That makes this
sugar, and reuses existing parts of the language and spec.

For constructors taking arguments, we could allow

var s = new String("hello, world") {frob: 42};

That looks less like one expression and more like two (but not two statements --
it would be spanked with a missing semicolon error at the left curly brace). 
Isn't it what Rhino did for its implement-random-Java-interface-in-JS syntax?

/be
Assignee: general → brendan
Priority: P5 → P3
Target Milestone: --- → mozilla1.9alpha
Summary: Array.toSource doesn't include non index props → Array.prototype.toSource excludes non-indexed enumerable properties
Flags: testcase?
> For constructors taking arguments, we could allow
> var s = new String("hello, world") {frob: 42};

good solution, 
a=[1,2,3];a.b=1; uneval(a); // can give ([1,2,3]{b:1})

or another way to represent a is [#1=[1,2,3], #1#.b=1][0];

test:-
a=[#1=[1,2,3], #1#.b=4][0];
a.b // gives 4
> For constructors taking arguments, we could allow
> var s = new String("hello, world") {frob: 42};

I come a bit late in the game, but if that's still open to discussion, why don't generalize that idea a bit more?

You can implement a "merge" behaviour when you concatenate objects.

So you can have:
var a = [1, 2, 3] {st: "hi"};
var s = "Hello world!" {foo: "fooqds", bar: "foobar"};

Also useful to apply defaults to an object:
function foo(opts)
{
var defaults = {method: "get", duration: 1.0, scroll: false};
opts = defaults opts;
...
}

Besides being useful to serialize any class, it also gives some syntactic sugar for merging objects, something that new js libraries are doing quite frequently (see Object.extend function in prototype, for instance).
Ops, the general "merge object concatenating them" interacts quite badly with semicolon insertion. Maybe a new operator to do the merge?
At some point this was rejected during an ECMA TG1 meeting. I don't remember the rationale exactly, but without toSource in the Edition 4 standard (toSource and uneval were never proposed; sharp variables and perhaps an earlier incarnation of toSource were, back in 1998 or so, and rejected for Edition 3), there does not seem to be any chance of standardization.

We certainly could experiment and extend SpiderMonkey and/or Rhino, in order to develop a strong proposal for next time. But, I'm a bad owner for this bug, so I'm throwing it back to the pool.

/be
Assignee: brendan → general
Given let, could we now serialize to an expression calling an anonymous function, which uses a literal for the numeric cases and then tacks on the non-numeric ones imperatively before returning?
Object.toSource is not really popular. Serializing to a function sounds bad. #hash# and stuff is gone.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.