archives

« Bugzilla Issues Index

#3111 — MapConstructor & WeakMapConstructor should do ToObject too?


http://people.mozilla.org/~jorendorff/es6-draft.html#sec-weakmap-iterable

7d: Let iter be the result of GetIterator(iterable).

For Set & WeakSet we are doing GetIteraror(ToObject(iterable))

However, maybe we should just change GetIterator to not throw on non Objects.


fixed in rev27 editor's draft


Allen, what was the resolution?


(In reply to Erik Arvidsson from comment #2)
> Allen, what was the resolution?

By passing ToObject(iterable) to GetIterator

If we made GetIterator not throw on none objects, then we'd have to define what it does instead. Return an empty iterator? After reviewing everyplace GetIterator is used, I don't think it is necessary.


(In reply to Allen Wirfs-Brock from comment #3)
> (In reply to Erik Arvidsson from comment #2)
> > Allen, what was the resolution?
>
> By passing ToObject(iterable) to GetIterator
>
> If we made GetIterator not throw on none objects, then we'd have to define
> what it does instead. Return an empty iterator? After reviewing everyplace
> GetIterator is used, I don't think it is necessary.

GetIterator + CheckIterator throws if not an object or the value of Get(obj, @@iterator) is not callable. It also throws if the result of that call is not an object.

An alternative approach would be to use CheckObjectCoercible and throw (throw for null and undefined). Then do the Get(value, @@iterator) and throw if not callable or the result of that call is not an object.

This is of course observable if you have a getter for Number.prototype[Symbol.iterator] and you check the type of this (in strict mode).


(In reply to Erik Arvidsson from comment #4)
> (In reply to Allen Wirfs-Brock from comment #3)
> > (In reply to Erik Arvidsson from comment #2)
> > > Allen, what was the resolution?
> >
> > By passing ToObject(iterable) to GetIterator
> >
> > If we made GetIterator not throw on none objects, then we'd have to define
> > what it does instead. Return an empty iterator? After reviewing everyplace
> > GetIterator is used, I don't think it is necessary.
>
> GetIterator + CheckIterator throws if not an object or the value of Get(obj,
> @@iterator) is not callable. It also throws if the result of that call is
> not an object.
>
> An alternative approach would be to use CheckObjectCoercible and throw
> (throw for null and undefined). Then do the Get(value, @@iterator) and throw
> if not callable or the result of that call is not an object.
>
> This is of course observable if you have a getter for
> Number.prototype[Symbol.iterator] and you check the type of this (in strict
> mode).

It's really up to the caller of GetIteator to decide if it wants to accept primitive values and and at what point it wants any observable ToObject operations to occur.

I don't really see any issues in the way it currently works.


(In reply to Allen Wirfs-Brock from comment #5)
> (In reply to Erik Arvidsson from comment #4)
> > (In reply to Allen Wirfs-Brock from comment #3)
> > > (In reply to Erik Arvidsson from comment #2)
> > > > Allen, what was the resolution?
> > >
> > > By passing ToObject(iterable) to GetIterator
> > >
> > > If we made GetIterator not throw on none objects, then we'd have to define
> > > what it does instead. Return an empty iterator? After reviewing everyplace
> > > GetIterator is used, I don't think it is necessary.
> >
> > GetIterator + CheckIterator throws if not an object or the value of Get(obj,
> > @@iterator) is not callable. It also throws if the result of that call is
> > not an object.
> >
> > An alternative approach would be to use CheckObjectCoercible and throw
> > (throw for null and undefined). Then do the Get(value, @@iterator) and throw
> > if not callable or the result of that call is not an object.
> >
> > This is of course observable if you have a getter for
> > Number.prototype[Symbol.iterator] and you check the type of this (in strict
> > mode).
>
> It's really up to the caller of GetIteator to decide if it wants to accept
> primitive values and and at what point it wants any observable ToObject
> operations to occur.
>
> I don't really see any issues in the way it currently works.

The problem right now is that GetIterator requires the argument to be an object. I would prefer if GetIterator worked on values and if the caller does not want to iterator values they can throw if not an object.

The way it is now creates a useless object (which is observable)


(In reply to Erik Arvidsson from comment #6)
I don't really see any issues in the way it currently works.
>
> The problem right now is that GetIterator requires the argument to be an
> object. I would prefer if GetIterator worked on values and if the caller
> does not want to iterator values they can throw if not an object.
>
> The way it is now creates a useless object (which is observable)

But that observable object is just the same as the semantics of
44[anyKey]
when anykey is an accessor property of Number.prototype which has a non-strict getter function. So I don't see why you are concerned about that observable object.

We could special case all the places where we use GetIterator so they each decide exactly which primitive values they want to accept. It it seems much more consistent for the normal behavior to just be ToObject.

finbally, while Number.prototype doesn't have an standard @@iterator, I don't think we would want to preclude somebody from defining it.


(In reply to Allen Wirfs-Brock from comment #7)
> (In reply to Erik Arvidsson from comment #6)
> I don't really see any issues in the way it currently works.
> >
> > The problem right now is that GetIterator requires the argument to be an
> > object. I would prefer if GetIterator worked on values and if the caller
> > does not want to iterator values they can throw if not an object.
> >
> > The way it is now creates a useless object (which is observable)
>
> But that observable object is just the same as the semantics of
> 44[anyKey]
> when anykey is an accessor property of Number.prototype which has a
> non-strict getter function. So I don't see why you are concerned about that
> observable object.

I'm not concerned about the observable effect but as it is now the spec mandates that you do a ToObject first or it will fail the test262 test for this edge case.

> We could special case all the places where we use GetIterator so they each
> decide exactly which primitive values they want to accept. It it seems much
> more consistent for the normal behavior to just be ToObject.

My point is that we should not special case GetIterator + CheckIterator. It should just do `value[Symbol.iterator]()` and not care what type value has.

> finbally, while Number.prototype doesn't have an standard @@iterator, I
> don't think we would want to preclude somebody from defining it.

Of course. I used Number.prototype as an example because it does not have an iterator in ES6.


(In reply to Erik Arvidsson from comment #8)
> (In reply to Allen Wirfs-Brock from comment #7)
> >

> > But that observable object is just the same as the semantics of
> > 44[anyKey]
> > when anykey is an accessor property of Number.prototype which has a
> > non-strict getter function. So I don't see why you are concerned about that
> > observable object.
>
> I'm not concerned about the observable effect but as it is now the spec
> mandates that you do a ToObject first or it will fail the test262 test for
> this edge case.

Right, the way I have it currently spec'ed
1. ToObject and any observable effects
2 Any oberable effects of Get @@iterator
3. IsCallable exceptions
3. object TypeCheck on result

44[anykey]() does:
1. CheckObjectCoercible/ToObject
2. Get anykey
3. IsCallable

So, the ordering of observable events is the same, which is presumably something that could/should be checked by test262

>
> > We could special case all the places where we use GetIterator so they each
> > decide exactly which primitive values they want to accept. It it seems much
> > more consistent for the normal behavior to just be ToObject.
>
> My point is that we should not special case GetIterator + CheckIterator. It
> should just do `value[Symbol.iterator]()` and not care what type value has.

But at the spec level we don't have a single abstraction operation that does the equivalent of 'value[Symbol.Iterator]()'. And we have plenty of places where we throw instead of coerce prior to calling a property.

I could do some restructuring and have some more abstract operations, but it wouldn't change the actual semantics and at this point in time, I doen't think it would be a high priority.


Of course, I may just be stubbornly missing your point. If so keeping trying and I'll probably eventually see it.


(In reply to Allen Wirfs-Brock from comment #9)

> Of course, I may just be stubbornly missing your point. If so keeping
> trying and I'll probably eventually see it.

I think you are missing my point. I'll try to create a diff on the spec with what I mean tomorrow.


fixed in rev27 draft