Re: Cross-global instanceof

2013-11-02 Thread Jake Verbaten
 What are the use cases for things like 'isGenerator'. When and why would
you need to know that an object  upon which you are going to invoke the
Iterator interface was/wasn't implemented by a generator.

[`co`][1] is a library similar to Task.js that allows you to use ES6
generators as async / await.

It allows you to yield multiple different types of future values and uses
polymorphic dispatch to the correct await implementation based on type
checks.

Here there is a genuine use case for overloading yield to implement an
async / await DSL that does the correct thing basd on the type of future
value that you yield within the generator.

In it's implementation it uses `isGenerator` and `isGeneratorFunction` (
https://github.com/visionmedia/co/blob/master/index.js#L153 ).

I also personally use an `isGenerator` function (
https://github.com/Raynos/gens/blob/master/index.js#L43 ) so that I can
implement the correct await semantics for the different types of future
values you are allowed to yield in my library `gens`

  [1]: https://github.com/visionmedia/co/blob/master/index.js#L153


On Thu, Oct 31, 2013 at 11:01 AM, Allen Wirfs-Brock
al...@wirfs-brock.comwrote:


 On Oct 31, 2013, at 9:43 AM, Brandon Benvie wrote:

  On 10/31/2013 8:50 AM, David Bruant wrote:
  I'm not sure it's worth making it work for jQuery. This is trying to
 make a good use of same-origin multi-global which shouldn't exist in the
 first place. Keeping same-origin access as it is and encouraging people to
 add @sandbox even on same-origin iframes seems like a better idea.
 
  Should the addition be a nicer Object.prototype.toString.call?
 
  You're right, it's not instanceof. But I definitely think the argument
 can be made that there is a need for checking if something is of a certain
 class. I'm finding myself wanting things like `isGenerator` and
 `isGeneratorFunction`, for example. There's countless examples of people
 re-purposing Object.prototype.toString to serve this functionality ad hoc.


 What are the use cases for things like 'isGenerator'. When and why would
 you need to know that an object  upon which you are going to invoke the
 Iterator interface was/wasn't implemented by a generator.  If the reason is
 to know whether or not you can use the throw method (the only real
 difference between the generator object interface and the Iterator
 interface) you can test:
 'throw' in possibleGenerator

 In general this sort of isFoo or obj.constructor === Foo class test is a
 bad smell in dynamic class based languages and tends to be a reflection of
 static nominal type thinking (which is fine in its own context, but JS is
 has a dynamic class model).

 Allen
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-02 Thread David Bruant

Le 02/11/2013 03:13, Allen Wirfs-Brock a écrit :

On Nov 1, 2013, at 6:05 PM, David Bruant wrote:

I'm not sure about proxy returning Proxy as tag name. Is that a good idea? 
Brand feels like something that could safely transparently cross proxies.

There is a note on in the ES6 draft on that Proxy case of O.P.toStirng that says: This could 
be used an isProxy test.  Do we really want that?  Nobody has answered that question yet?  
What do you mean by band transmitted accross proxies.  ES6 has no general concept of 
brand.

lousy language, my mistake. I meant @@toStringTag.


We could handle that case by internally doing O.p.toString.cal(this.[[target]]) 
for the proxy case.  Or we could just turn it into this.toString().  But 
neither of those seem particularly correct, in general.

Or we could simply not special case Proxy exotic objects and then Proxies would 
be handled like any other object, the value of the objects @@toStringTag 
property would be accessed and used to compose the toString result.
Or what about a third optional argument to the Proxy constructor to set 
the @@toStringTag?


David
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-02 Thread Allen Wirfs-Brock

On Nov 1, 2013, at 7:13 PM, Allen Wirfs-Brock wrote:

 
 On Nov 1, 2013, at 6:05 PM, David Bruant wrote:
 
 Le 02/11/2013 01:08, Brandon Benvie a écrit :
 On 11/1/2013 4:59 PM, Brandon Benvie wrote:
 On 11/1/2013 4:31 PM, Brandon Benvie wrote:
 In the spec for Object.prototype.toString:
 
 'If tag is any of Arguments, Array, Boolean, Date, Error, 
 Function, Number, RegExp, or String and SameValue(tag, 
 builtinTag) is false, then let tag be the string value ~ concatenated 
 with the current value of tag.'
 
 An interesting consequence of this is that a Proxy for any of these will 
 default to being ~ + target class. So 
 `Object.prototype.toString.call(new Proxy([], {}))` is [object ~Array]. 
 But it seems the shipped has already sailed on Proxies being conspicuously 
 not interchangeable with their targets in many cases...
 
 Actually that's incorrect. Proxies explicitly will return Proxy for their 
 tag. Same problem though.
 In what other ways the ship has sailed?
 At least regular objects and arrays can be faithfully interchanged I think, 
 no? Things get complicated with Date/WeakMap/etc because of private state, 
 but I remain hopeful a solution can be found in the ES7 timeframe (or 
 whatever the next iteration is called).
 
 Note, proxies do not transparently operate on target objects that have 
 private internal state or any sort of internal dependencies upon object 
 identify.  You can define a handler that over-rides most of the traps and 
 make it work,  but for most built-ins doing something like:
  Proxy (new Date, {} )  
 will give you an object that throws when methods of the target object are 
 invoked upon it.

I just realized that the current specification of O.p.toString is a example of 
a method that has a identity dependency and hence won't work with default Proxy 
forwarding. As currently specified,
   Proxy({}, {}).toString()
would yield [object Proxy] rather than [object Object] as you (and I) might 
have expected.  The reason is that the default handler will lookup toString 
using the target object's [[Prototype]] chain and find the implementation in 
Object.prototype.  But when it invokes that method the default handler will 
pass the Proxy object rather than the target object of the this value.  Hence: 
[[object Proxy]].

This seems too wrong to me, but I'm not yet clear on an appropriate fix within 
O.p.toString.

 
 I'm not sure about proxy returning Proxy as tag name. Is that a good idea? 
 Brand feels like something that could safely transparently cross proxies.
 
 There is a note on in the ES6 draft on that Proxy case of O.P.toStirng that 
 says: This could be used an isProxy test.  Do we really want that?  Nobody 
 has answered that question yet?  What do you mean by band transmitted 
 accross proxies.  ES6 has no general concept of brand.
 
Note, that the Proxy proposal originally came with a Proxy.isProxy function and 
after various discussions (for example, 
https://mail.mozilla.org/pipermail/es-discuss/2011-July/015935.html ) it was 
removed.  An brand check approach that that identifies Proxies (including the 
current spec. for O.p.toString) is a backdoor way of implementing 
Proxy.isProxy. If the reasons for removing Proxy.isProxy are valid then we 
should be providing such a backdoor.

Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-02 Thread Mark S. Miller
On Sat, Nov 2, 2013 at 10:55 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:

 [...] If the reasons for removing Proxy.isProxy are valid then we should
 be providing such a backdoor.


not?


-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-02 Thread Allen Wirfs-Brock

On Nov 2, 2013, at 11:25 AM, Mark S. Miller wrote:

 On Sat, Nov 2, 2013 at 10:55 AM, Allen Wirfs-Brock al...@wirfs-brock.com 
 wrote:
 [...] If the reasons for removing Proxy.isProxy are valid then we should be 
 providing such a backdoor.
 
 not?
 

shouldn't




 
 -- 
 Cheers,
 --MarkM

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Andrea Giammarchi
Sure, so Allen asked me a real case to show, and I've done it. Now you
please show me a real case when you pass a revival function to `JSON.parse`
that is from another realm, explaining why, as I've done for mine, thanks.

Best Regards


On Thu, Oct 31, 2013 at 7:41 PM, Oliver Hunt oli...@apple.com wrote:


 On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi andrea.giammar...@gmail.com
 wrote:

  Allen, in which place on current known universe, when you parse a
 JSON.string, your reviver function receives objects from another realm,
 exactly?
 Please try to keep the discourse polite.

 That said this is fairly trivial

 realm a
 function reviver(…) { … }
 /

 realm b
 JSON.parse(… realm a.reviver …)
 /

 now the realm of the objects created by the JSON object differ from the
 realm that the reviver function is working in.

 —Oliver




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Andrea Giammarchi
also, your reviver would receive objects from the realm I am checking with
that code ... so your reviver will receive object from the **expected**
realm ... just to clarify, for future readers.

Still all ears listening to that case I've never, honestly, considered!

Thanks


On Thu, Oct 31, 2013 at 11:07 PM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 Sure, so Allen asked me a real case to show, and I've done it. Now you
 please show me a real case when you pass a revival function to `JSON.parse`
 that is from another realm, explaining why, as I've done for mine, thanks.

 Best Regards


 On Thu, Oct 31, 2013 at 7:41 PM, Oliver Hunt oli...@apple.com wrote:


 On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

  Allen, in which place on current known universe, when you parse a
 JSON.string, your reviver function receives objects from another realm,
 exactly?
 Please try to keep the discourse polite.

 That said this is fairly trivial

 realm a
 function reviver(…) { … }
 /

 realm b
 JSON.parse(… realm a.reviver …)
 /

 now the realm of the objects created by the JSON object differ from the
 realm that the reviver function is working in.

 —Oliver





___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Oliver Hunt

On Nov 1, 2013, at 7:23 PM, Andrea Giammarchi andrea.giammar...@gmail.com 
wrote:

 also, your reviver would receive objects from the realm I am checking with 
 that code ... so your reviver will receive object from the **expected** realm 
 ... just to clarify, for future readers.
 

I don’t understand what you’re saying here

if your reviver is in realm A, and says

function reviver(foo) {
…
  if (foo instance of Array) alert(“Array!”)
...
}

And realm B says

JSON.parse(…, realm A.reviver)

You will never get to the alert.

As far as use cases, i recall multiple websites using invisible iframes as 
“modules” where multiple realms would use a shared group of functions from a 
single realm

—Oliver

 Still all ears listening to that case I've never, honestly, considered!
 
 Thanks
 
 
 On Thu, Oct 31, 2013 at 11:07 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:
 Sure, so Allen asked me a real case to show, and I've done it. Now you please 
 show me a real case when you pass a revival function to `JSON.parse` that is 
 from another realm, explaining why, as I've done for mine, thanks.
 
 Best Regards
 
 
 On Thu, Oct 31, 2013 at 7:41 PM, Oliver Hunt oli...@apple.com wrote:
 
 On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi andrea.giammar...@gmail.com 
 wrote:
 
  Allen, in which place on current known universe, when you parse a 
  JSON.string, your reviver function receives objects from another realm, 
  exactly?
 Please try to keep the discourse polite.
 
 That said this is fairly trivial
 
 realm a
 function reviver(…) { … }
 /
 
 realm b
 JSON.parse(… realm a.reviver …)
 /
 
 now the realm of the objects created by the JSON object differ from the realm 
 that the reviver function is working in.
 
 —Oliver
 
 
 
 
 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Andrea Giammarchi
I have no idea who is doing that and why but yes, in that case I would
never have used instanceof so my example is still valid as use case itself.

Cheers


On Thu, Oct 31, 2013 at 11:54 PM, Oliver Hunt oli...@apple.com wrote:


 On Nov 1, 2013, at 7:23 PM, Andrea Giammarchi andrea.giammar...@gmail.com
 wrote:

 also, your reviver would receive objects from the realm I am checking with
 that code ... so your reviver will receive object from the **expected**
 realm ... just to clarify, for future readers.


 I don’t understand what you’re saying here

 if your reviver is in realm A, and says

 function reviver(foo) {
 …
   if (foo instance of Array) alert(“Array!”)
 ...
 }

 And realm B says

 JSON.parse(…, realm A.reviver)

 You will never get to the alert.

 As far as use cases, i recall multiple websites using invisible iframes as
 “modules” where multiple realms would use a shared group of functions from
 a single realm

 —Oliver

 Still all ears listening to that case I've never, honestly, considered!

 Thanks


 On Thu, Oct 31, 2013 at 11:07 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 Sure, so Allen asked me a real case to show, and I've done it. Now you
 please show me a real case when you pass a revival function to `JSON.parse`
 that is from another realm, explaining why, as I've done for mine, thanks.

 Best Regards


 On Thu, Oct 31, 2013 at 7:41 PM, Oliver Hunt oli...@apple.com wrote:


 On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

  Allen, in which place on current known universe, when you parse a
 JSON.string, your reviver function receives objects from another realm,
 exactly?
 Please try to keep the discourse polite.

 That said this is fairly trivial

 realm a
 function reviver(…) { … }
 /

 realm b
 JSON.parse(… realm a.reviver …)
 /

 now the realm of the objects created by the JSON object differ from the
 realm that the reviver function is working in.

 —Oliver







___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Anne van Kesteren
On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 [isSpecialString]() {return isSpecialString in this};

So this is basically what we have for DOM objects right now. And what
we're asking for is having this elevated to language-supported
construct. Be it in the form of a method or something else. It's not
really clear why sometimes you would use if brand in obj and other
times Array.isArray(obj). Seems rather messy.


-- 
http://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Allen Wirfs-Brock

On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

 On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 [isSpecialString]() {return isSpecialString in this};
 
 So this is basically what we have for DOM objects right now. And what
 we're asking for is having this elevated to language-supported
 construct. Be it in the form of a method or something else. It's not
 really clear why sometimes you would use if brand in obj and other
 times Array.isArray(obj). Seems rather messy.

Array.isArray is a legacy artifact so I'm not going to try to generalize from 
it.

But, in general, the distinction is between asking does this object appear to 
expose the behavior I need and is this object an instance of a specific known 
implementation of the behavior I need.  Let's call the first question duck 
typing and the second branding. Duck typing is a weaker test but allows for 
a lot of flexibility and extensibility. Branding gives you reliable knowledge 
about  certain aspects of a branded object.  But it is less flexible and and 
systems that extensively using branding are often harder to extend. IMO 
branding is over used.

Array.isArray is a specific brand test based upon how the implementation of how 
property definition interacts with the value of the 'length' property. 

ES currently proves lots of ways to do duck type testing.  Built-in objects 
(including host objects) can implement branding and brand testing using various 
techniques but ES currently (including ES6) is very limited in its language 
level sort for reliable branding.  The best we have to offer in ES6 is 
WeakMaps. In the future, we probably will add mechanism that make it easier to 
define branded objects defined via ES code. 

But, before you brand something really think carefully about why you need such 
a brand. It may not really be necessary.

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Andrea Giammarchi
Allen I think we all agree duck typing is more flexible, powerful, easy,
etc etc ... but since you mentioned, how would do distinguish between a
`Map` and a `WeakMap` without passing through the branding check ?

That's a very good example indeed, `'has' in obj` or `'set' in obj` does
not grant you any behavior with the signature itself (e.g. `WekMap`
does/did not accept primitives as key)

AFAIK WebIDL is entirely based on branding, regardless it's a good or a bad
thing, that's the way W3C describes things since quite ever (and
implement them in Java too ... anyway)

Why there's no easy way to check for branding if not abusing
`Object.prototype.toString` ?

If so many libraries are using it because of the cross realm, maybe there
is a need for some similar mechanism and implemented in core would make
everybody life easier/faster ?

The option you give us is: keep abusing `Object.prototype.toString` ...
that's OK but it seems to be a dirty solution.

Cheers




On Fri, Nov 1, 2013 at 11:52 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:


 On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

  On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
  al...@wirfs-brock.com wrote:
  [isSpecialString]() {return isSpecialString in this};
 
  So this is basically what we have for DOM objects right now. And what
  we're asking for is having this elevated to language-supported
  construct. Be it in the form of a method or something else. It's not
  really clear why sometimes you would use if brand in obj and other
  times Array.isArray(obj). Seems rather messy.

 Array.isArray is a legacy artifact so I'm not going to try to generalize
 from it.

 But, in general, the distinction is between asking does this object
 appear to expose the behavior I need and is this object an instance of a
 specific known implementation of the behavior I need.  Let's call the
 first question duck typing and the second branding. Duck typing is a
 weaker test but allows for a lot of flexibility and extensibility. Branding
 gives you reliable knowledge about  certain aspects of a branded object.
  But it is less flexible and and systems that extensively using branding
 are often harder to extend. IMO branding is over used.

 Array.isArray is a specific brand test based upon how the implementation
 of how property definition interacts with the value of the 'length'
 property.

 ES currently proves lots of ways to do duck type testing.  Built-in
 objects (including host objects) can implement branding and brand testing
 using various techniques but ES currently (including ES6) is very limited
 in its language level sort for reliable branding.  The best we have to
 offer in ES6 is WeakMaps. In the future, we probably will add mechanism
 that make it easier to define branded objects defined via ES code.

 But, before you brand something really think carefully about why you need
 such a brand. It may not really be necessary.

 Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Mark S. Miller
On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 Allen I think we all agree duck typing is more flexible, powerful, easy,
 etc etc ... but since you mentioned, how would do distinguish between a
 `Map` and a `WeakMap` without passing through the branding check ?

 That's a very good example indeed, `'has' in obj` or `'set' in obj` does
 not grant you any behavior with the signature itself (e.g. `WekMap`
 does/did not accept primitives as key)

 AFAIK WebIDL is entirely based on branding, regardless it's a good or a
 bad thing, that's the way W3C describes things since quite ever (and
 implement them in Java too ... anyway)

 Why there's no easy way to check for branding if not abusing
 `Object.prototype.toString` ?

 If so many libraries are using it because of the cross realm, maybe there
 is a need for some similar mechanism and implemented in core would make
 everybody life easier/faster ?

 The option you give us is: keep abusing `Object.prototype.toString` ...
 that's OK but it seems to be a dirty solution.


In ES5, Object.prototype.toString was a reliable brand check. It no longer
is in ES6.




 Cheers




 On Fri, Nov 1, 2013 at 11:52 AM, Allen Wirfs-Brock 
 al...@wirfs-brock.comwrote:


 On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

  On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
  al...@wirfs-brock.com wrote:
  [isSpecialString]() {return isSpecialString in this};
 
  So this is basically what we have for DOM objects right now. And what
  we're asking for is having this elevated to language-supported
  construct. Be it in the form of a method or something else. It's not
  really clear why sometimes you would use if brand in obj and other
  times Array.isArray(obj). Seems rather messy.

 Array.isArray is a legacy artifact so I'm not going to try to generalize
 from it.

 But, in general, the distinction is between asking does this object
 appear to expose the behavior I need and is this object an instance of a
 specific known implementation of the behavior I need.  Let's call the
 first question duck typing and the second branding. Duck typing is a
 weaker test but allows for a lot of flexibility and extensibility. Branding
 gives you reliable knowledge about  certain aspects of a branded object.
  But it is less flexible and and systems that extensively using branding
 are often harder to extend. IMO branding is over used.

 Array.isArray is a specific brand test based upon how the implementation
 of how property definition interacts with the value of the 'length'
 property.

 ES currently proves lots of ways to do duck type testing.  Built-in
 objects (including host objects) can implement branding and brand testing
 using various techniques but ES currently (including ES6) is very limited
 in its language level sort for reliable branding.  The best we have to
 offer in ES6 is WeakMaps. In the future, we probably will add mechanism
 that make it easier to define branded objects defined via ES code.

 But, before you brand something really think carefully about why you need
 such a brand. It may not really be necessary.

 Allen



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Andrea Giammarchi
Thanks Mark,
so how is anyone supposed to be sure about or check a Brand in ES6 then?


On Fri, Nov 1, 2013 at 1:00 PM, Mark S. Miller erig...@google.com wrote:




 On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 Allen I think we all agree duck typing is more flexible, powerful, easy,
 etc etc ... but since you mentioned, how would do distinguish between a
 `Map` and a `WeakMap` without passing through the branding check ?

 That's a very good example indeed, `'has' in obj` or `'set' in obj` does
 not grant you any behavior with the signature itself (e.g. `WekMap`
 does/did not accept primitives as key)

 AFAIK WebIDL is entirely based on branding, regardless it's a good or a
 bad thing, that's the way W3C describes things since quite ever (and
 implement them in Java too ... anyway)

 Why there's no easy way to check for branding if not abusing
 `Object.prototype.toString` ?

 If so many libraries are using it because of the cross realm, maybe there
 is a need for some similar mechanism and implemented in core would make
 everybody life easier/faster ?

 The option you give us is: keep abusing `Object.prototype.toString` ...
 that's OK but it seems to be a dirty solution.


 In ES5, Object.prototype.toString was a reliable brand check. It no longer
 is in ES6.




 Cheers




 On Fri, Nov 1, 2013 at 11:52 AM, Allen Wirfs-Brock al...@wirfs-brock.com
  wrote:


 On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

  On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
  al...@wirfs-brock.com wrote:
  [isSpecialString]() {return isSpecialString in this};
 
  So this is basically what we have for DOM objects right now. And what
  we're asking for is having this elevated to language-supported
  construct. Be it in the form of a method or something else. It's not
  really clear why sometimes you would use if brand in obj and other
  times Array.isArray(obj). Seems rather messy.

 Array.isArray is a legacy artifact so I'm not going to try to generalize
 from it.

 But, in general, the distinction is between asking does this object
 appear to expose the behavior I need and is this object an instance of a
 specific known implementation of the behavior I need.  Let's call the
 first question duck typing and the second branding. Duck typing is a
 weaker test but allows for a lot of flexibility and extensibility. Branding
 gives you reliable knowledge about  certain aspects of a branded object.
  But it is less flexible and and systems that extensively using branding
 are often harder to extend. IMO branding is over used.

 Array.isArray is a specific brand test based upon how the implementation
 of how property definition interacts with the value of the 'length'
 property.

 ES currently proves lots of ways to do duck type testing.  Built-in
 objects (including host objects) can implement branding and brand testing
 using various techniques but ES currently (including ES6) is very limited
 in its language level sort for reliable branding.  The best we have to
 offer in ES6 is WeakMaps. In the future, we probably will add mechanism
 that make it easier to define branded objects defined via ES code.

 But, before you brand something really think carefully about why you
 need such a brand. It may not really be necessary.

 Allen



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




 --
 Cheers,
 --MarkM

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Mark S. Miller
For the ES6 builtin types, I have no idea.

For abstractions you define yourself, your abstraction can brand its
objects using an encapsulated WeakSet or WeakMap. This will work, but with
two problems:

* Awkward syntax until more directly supported by ES7 relationships.

* Sucky performance until Weak* implementations transpose their internal
representation, as recommended by the relationships strawman. Note that
implementations should do this transpose asap, as it is purely an
optimization fully applicable to ES6. It has no dependence on the rest of
the relationships strawman.



On Fri, Nov 1, 2013 at 1:03 PM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 Thanks Mark,
 so how is anyone supposed to be sure about or check a Brand in ES6
 then?


 On Fri, Nov 1, 2013 at 1:00 PM, Mark S. Miller erig...@google.com wrote:




 On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 Allen I think we all agree duck typing is more flexible, powerful, easy,
 etc etc ... but since you mentioned, how would do distinguish between a
 `Map` and a `WeakMap` without passing through the branding check ?

 That's a very good example indeed, `'has' in obj` or `'set' in obj` does
 not grant you any behavior with the signature itself (e.g. `WekMap`
 does/did not accept primitives as key)

 AFAIK WebIDL is entirely based on branding, regardless it's a good or a
 bad thing, that's the way W3C describes things since quite ever (and
 implement them in Java too ... anyway)

 Why there's no easy way to check for branding if not abusing
 `Object.prototype.toString` ?

 If so many libraries are using it because of the cross realm, maybe
 there is a need for some similar mechanism and implemented in core would
 make everybody life easier/faster ?

 The option you give us is: keep abusing `Object.prototype.toString` ...
 that's OK but it seems to be a dirty solution.


 In ES5, Object.prototype.toString was a reliable brand check. It no
 longer is in ES6.




 Cheers




 On Fri, Nov 1, 2013 at 11:52 AM, Allen Wirfs-Brock 
 al...@wirfs-brock.com wrote:


 On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

  On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
  al...@wirfs-brock.com wrote:
  [isSpecialString]() {return isSpecialString in this};
 
  So this is basically what we have for DOM objects right now. And what
  we're asking for is having this elevated to language-supported
  construct. Be it in the form of a method or something else. It's not
  really clear why sometimes you would use if brand in obj and other
  times Array.isArray(obj). Seems rather messy.

 Array.isArray is a legacy artifact so I'm not going to try to
 generalize from it.

 But, in general, the distinction is between asking does this object
 appear to expose the behavior I need and is this object an instance of a
 specific known implementation of the behavior I need.  Let's call the
 first question duck typing and the second branding. Duck typing is a
 weaker test but allows for a lot of flexibility and extensibility. Branding
 gives you reliable knowledge about  certain aspects of a branded object.
  But it is less flexible and and systems that extensively using branding
 are often harder to extend. IMO branding is over used.

 Array.isArray is a specific brand test based upon how the
 implementation of how property definition interacts with the value of the
 'length' property.

 ES currently proves lots of ways to do duck type testing.  Built-in
 objects (including host objects) can implement branding and brand testing
 using various techniques but ES currently (including ES6) is very limited
 in its language level sort for reliable branding.  The best we have to
 offer in ES6 is WeakMaps. In the future, we probably will add mechanism
 that make it easier to define branded objects defined via ES code.

 But, before you brand something really think carefully about why you
 need such a brand. It may not really be necessary.

 Allen



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




 --
 Cheers,
 --MarkM





-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Mark Miller
http://wiki.ecmascript.org/doku.php?id=strawman:relationships


On Fri, Nov 1, 2013 at 1:11 PM, Mark S. Miller erig...@google.com wrote:

 For the ES6 builtin types, I have no idea.

 For abstractions you define yourself, your abstraction can brand its
 objects using an encapsulated WeakSet or WeakMap. This will work, but with
 two problems:

 * Awkward syntax until more directly supported by ES7 relationships.

 * Sucky performance until Weak* implementations transpose their internal
 representation, as recommended by the relationships strawman. Note that
 implementations should do this transpose asap, as it is purely an
 optimization fully applicable to ES6. It has no dependence on the rest of
 the relationships strawman.



 On Fri, Nov 1, 2013 at 1:03 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 Thanks Mark,
 so how is anyone supposed to be sure about or check a Brand in ES6
 then?


 On Fri, Nov 1, 2013 at 1:00 PM, Mark S. Miller erig...@google.comwrote:




 On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 Allen I think we all agree duck typing is more flexible, powerful,
 easy, etc etc ... but since you mentioned, how would do distinguish between
 a `Map` and a `WeakMap` without passing through the branding check ?

 That's a very good example indeed, `'has' in obj` or `'set' in obj`
 does not grant you any behavior with the signature itself (e.g. `WekMap`
 does/did not accept primitives as key)

 AFAIK WebIDL is entirely based on branding, regardless it's a good or a
 bad thing, that's the way W3C describes things since quite ever (and
 implement them in Java too ... anyway)

 Why there's no easy way to check for branding if not abusing
 `Object.prototype.toString` ?

 If so many libraries are using it because of the cross realm, maybe
 there is a need for some similar mechanism and implemented in core would
 make everybody life easier/faster ?

 The option you give us is: keep abusing `Object.prototype.toString` ...
 that's OK but it seems to be a dirty solution.


 In ES5, Object.prototype.toString was a reliable brand check. It no
 longer is in ES6.




 Cheers




 On Fri, Nov 1, 2013 at 11:52 AM, Allen Wirfs-Brock 
 al...@wirfs-brock.com wrote:


 On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:

  On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock
  al...@wirfs-brock.com wrote:
  [isSpecialString]() {return isSpecialString in this};
 
  So this is basically what we have for DOM objects right now. And what
  we're asking for is having this elevated to language-supported
  construct. Be it in the form of a method or something else. It's not
  really clear why sometimes you would use if brand in obj and other
  times Array.isArray(obj). Seems rather messy.

 Array.isArray is a legacy artifact so I'm not going to try to
 generalize from it.

 But, in general, the distinction is between asking does this object
 appear to expose the behavior I need and is this object an instance of a
 specific known implementation of the behavior I need.  Let's call the
 first question duck typing and the second branding. Duck typing is a
 weaker test but allows for a lot of flexibility and extensibility. 
 Branding
 gives you reliable knowledge about  certain aspects of a branded object.
  But it is less flexible and and systems that extensively using branding
 are often harder to extend. IMO branding is over used.

 Array.isArray is a specific brand test based upon how the
 implementation of how property definition interacts with the value of the
 'length' property.

 ES currently proves lots of ways to do duck type testing.  Built-in
 objects (including host objects) can implement branding and brand testing
 using various techniques but ES currently (including ES6) is very limited
 in its language level sort for reliable branding.  The best we have to
 offer in ES6 is WeakMaps. In the future, we probably will add mechanism
 that make it easier to define branded objects defined via ES code.

 But, before you brand something really think carefully about why you
 need such a brand. It may not really be necessary.

 Allen



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




 --
 Cheers,
 --MarkM





 --
 Cheers,
 --MarkM

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Allen Wirfs-Brock

On Nov 1, 2013, at 12:16 PM, Andrea Giammarchi wrote:

 Allen I think we all agree duck typing is more flexible, powerful, easy, etc 
 etc ... but since you mentioned, how would do distinguish between a `Map` and 
 a `WeakMap` without passing through the branding check ?
 
 That's a very good example indeed, `'has' in obj` or `'set' in obj` does not 
 grant you any behavior with the signature itself (e.g. `WekMap` does/did not 
 accept primitives as key)

You can behaviorally distinguish between a Map and a WeakMap by the presence or 
absence of the 'forEach' or @@iterator property.  But why would you need to do 
that sort of discrimination?

If you need a map that is Iterable and somebody passes you a WeakMap that's a 
bug. An exception will be thrown when you try to iterate over it.  Similarly, 
if you need a map that accepts primitive values as keys and somebody passes you 
a WeakMap that's also a bug and will result in downstream exceptions.  What are 
the use case where you would want to accept either a Map or WeakMap and take 
different control paths depending upon which as passed? 

 
 AFAIK WebIDL is entirely based on branding, regardless it's a good or a bad 
 thing, that's the way W3C describes things since quite ever (and implement 
 them in Java too ... anyway)
So? Why should that restriction be lifted in a manner that allows multiple 
independent implementations or extensions of DOM interfaces to peacefully 
coexist.

 
 Why there's no easy way to check for branding if not abusing 
 `Object.prototype.toString` ?

Because there is no single semantics for branding.  What do you want you brand 
to mean.  For example, all of the branding in ES6 is subclass friendly.  Maps 
are branded and most Map methods will only work on Map branded objects.  But 
subclass instances of Map are (by default, you can make it otherwise) are also 
branded such that the Map methods will work for them.

In other circumstances, a developer may decide that they do not want subclass 
instances to share branding with a superclass.

In some cases it may be desirable for an individual object to carry multiple 
brands.

You can look at Realm associations of ES functions as form of branding...

What is the single easy test that encompasses all of these use cases, and others

 If so many libraries are using it because of the cross realm, maybe there is 
 a need for some similar mechanism and implemented in core would make 
 everybody life easier/faster ?

Arguably, the real issue here is the ad hoc semantics of Realms that have been 
implemented in browsers and the same-but-different built-ins that can be 
referenced cross Realms.

 
 The option you give us is: keep abusing `Object.prototype.toString` ... 
 that's OK but it seems to be a dirty solution.

As Mark mentions in a subsequent message.  ES6 O.p.toString only provides brand 
checking for legacy ES=5 built-ins.  It won't brand check Maps for you.  That 
is intentional.

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Allen Wirfs-Brock

On Nov 1, 2013, at 1:11 PM, Mark S. Miller wrote:

 For the ES6 builtin types, I have no idea.
 

Most branded ES6 built-ins have non-destructive brand-checking methods that 
call be used to perform brand checks.

For example,

function isMap(obj) {
   try {Map.prototype.size.call(obj); return true} catch (e) {return false}
}


 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Mark S. Miller
On Fri, Nov 1, 2013 at 4:03 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:


 On Nov 1, 2013, at 12:16 PM, Andrea Giammarchi wrote:

  Allen I think we all agree duck typing is more flexible, powerful, easy,
 etc etc ... but since you mentioned, how would do distinguish between a
 `Map` and a `WeakMap` without passing through the branding check ?
 
  That's a very good example indeed, `'has' in obj` or `'set' in obj` does
 not grant you any behavior with the signature itself (e.g. `WekMap`
 does/did not accept primitives as key)

 You can behaviorally distinguish between a Map and a WeakMap by the
 presence or absence of the 'forEach' or @@iterator property.  But why would
 you need to do that sort of discrimination?

 If you need a map that is Iterable and somebody passes you a WeakMap
 that's a bug. An exception will be thrown when you try to iterate over it.
  Similarly, if you need a map that accepts primitive values as keys and
 somebody passes you a WeakMap that's also a bug and will result in
 downstream exceptions.  What are the use case where you would want to
 accept either a Map or WeakMap and take different control paths depending
 upon which as passed?

 
  AFAIK WebIDL is entirely based on branding, regardless it's a good or a
 bad thing, that's the way W3C describes things since quite ever (and
 implement them in Java too ... anyway)
 So? Why should that restriction be lifted in a manner that allows multiple
 independent implementations or extensions of DOM interfaces to peacefully
 coexist.

 
  Why there's no easy way to check for branding if not abusing
 `Object.prototype.toString` ?

 Because there is no single semantics for branding.  What do you want you
 brand to mean.  For example, all of the branding in ES6 is subclass
 friendly.  Maps are branded and most Map methods will only work on Map
 branded objects.  But subclass instances of Map are (by default, you can
 make it otherwise) are also branded such that the Map methods will work for
 them.

 In other circumstances, a developer may decide that they do not want
 subclass instances to share branding with a superclass.

 In some cases it may be desirable for an individual object to carry
 multiple brands.

 You can look at Realm associations of ES functions as form of branding...

 What is the single easy test that encompasses all of these use cases, and
 others

  If so many libraries are using it because of the cross realm, maybe
 there is a need for some similar mechanism and implemented in core would
 make everybody life easier/faster ?

 Arguably, the real issue here is the ad hoc semantics of Realms that have
 been implemented in browsers and the same-but-different built-ins that can
 be referenced cross Realms.

 
  The option you give us is: keep abusing `Object.prototype.toString` ...
 that's OK but it seems to be a dirty solution.

 As Mark mentions in a subsequent message.  ES6 O.p.toString only provides
 brand checking for legacy ES=5 built-ins.


Hi Allen, perhaps I misunderstood. But I thought that as of ES6,
O.p.toString can't be used for reliable brand checking of anything,
including legacy ES=5 built-ins. Not so? How would I do such a check of a
legacy built-in in ES6?




  It won't brand check Maps for you.  That is intentional.

 Allen


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Brandon Benvie

On 11/1/2013 4:29 PM, Mark S. Miller wrote:
Hi Allen, perhaps I misunderstood. But I thought that as of ES6, 
O.p.toString can't be used for reliable brand checking of anything, 
including legacy ES=5 built-ins. Not so? How would I do such a check 
of a legacy built-in in ES6?


In the spec for Object.prototype.toString:

'If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, Number, RegExp, or String and SameValue(tag, 
builtinTag) is false, then let tag be the string value ~ concatenated 
with the current value of tag.'

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Mark S. Miller
I just read
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring
and
agree that it continues to preserve the brand checks that were reliable in
ES5.

Cool! Thanks!


On Fri, Nov 1, 2013 at 4:31 PM, Brandon Benvie bben...@mozilla.com wrote:

 On 11/1/2013 4:29 PM, Mark S. Miller wrote:

 Hi Allen, perhaps I misunderstood. But I thought that as of ES6,
 O.p.toString can't be used for reliable brand checking of anything,
 including legacy ES=5 built-ins. Not so? How would I do such a check of a
 legacy built-in in ES6?


 In the spec for Object.prototype.toString:

 'If tag is any of Arguments, Array, Boolean, Date, Error,
 Function, Number, RegExp, or String and SameValue(tag, builtinTag)
 is false, then let tag be the string value ~ concatenated with the
 current value of tag.'

 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Brandon Benvie

On 11/1/2013 4:31 PM, Brandon Benvie wrote:

In the spec for Object.prototype.toString:

'If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, Number, RegExp, or String and SameValue(tag, 
builtinTag) is false, then let tag be the string value ~ 
concatenated with the current value of tag.'


An interesting consequence of this is that a Proxy for any of these will 
default to being ~ + target class. So 
`Object.prototype.toString.call(new Proxy([], {}))` is [object 
~Array]. But it seems the shipped has already sailed on Proxies being 
conspicuously not interchangeable with their targets in many cases...

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Brandon Benvie

On 11/1/2013 4:59 PM, Brandon Benvie wrote:

On 11/1/2013 4:31 PM, Brandon Benvie wrote:

In the spec for Object.prototype.toString:

'If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, Number, RegExp, or String and SameValue(tag, 
builtinTag) is false, then let tag be the string value ~ 
concatenated with the current value of tag.'


An interesting consequence of this is that a Proxy for any of these 
will default to being ~ + target class. So 
`Object.prototype.toString.call(new Proxy([], {}))` is [object 
~Array]. But it seems the shipped has already sailed on Proxies being 
conspicuously not interchangeable with their targets in many cases...


Actually that's incorrect. Proxies explicitly will return Proxy for 
their tag. Same problem though.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread David Bruant

Le 02/11/2013 01:08, Brandon Benvie a écrit :

On 11/1/2013 4:59 PM, Brandon Benvie wrote:

On 11/1/2013 4:31 PM, Brandon Benvie wrote:

In the spec for Object.prototype.toString:

'If tag is any of Arguments, Array, Boolean, Date, Error, 
Function, Number, RegExp, or String and SameValue(tag, 
builtinTag) is false, then let tag be the string value ~ 
concatenated with the current value of tag.'


An interesting consequence of this is that a Proxy for any of these 
will default to being ~ + target class. So 
`Object.prototype.toString.call(new Proxy([], {}))` is [object 
~Array]. But it seems the shipped has already sailed on Proxies 
being conspicuously not interchangeable with their targets in many 
cases...


Actually that's incorrect. Proxies explicitly will return Proxy for 
their tag. Same problem though.

In what other ways the ship has sailed?
At least regular objects and arrays can be faithfully interchanged I 
think, no? Things get complicated with Date/WeakMap/etc because of 
private state, but I remain hopeful a solution can be found in the ES7 
timeframe (or whatever the next iteration is called).


I'm not sure about proxy returning Proxy as tag name. Is that a good 
idea? Brand feels like something that could safely transparently cross 
proxies.


David
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Brandon Benvie

On 11/1/2013 7:13 PM, Allen Wirfs-Brock wrote:

Or we could simply not special case Proxy exotic objects and then Proxies would 
be handled like any other object, the value of the objects @@toStringTag 
property would be accessed and used to compose the toString result.


Which would result in things like [object ~Array]. That'd probably be 
preferable than always returning [object Proxy] because at least you 
have the option of special casing it if you desire. I don't know though, 
because a Proxy for a Map would return [object Map], making it 
indistinguishable from a map yet it's still just as useless as a Proxy 
for a Date.


This just reminds me how cold I still am on the fact that you can't 
easily one-off Proxy anything that's not a plain Object, Array, or 
Function because of the lack of an invoke trap and every other type of 
built-in has private state... but I suppose this isn't really the thread 
for that.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Allen Wirfs-Brock

On Nov 1, 2013, at 7:27 PM, Brandon Benvie wrote:

 On 11/1/2013 7:13 PM, Allen Wirfs-Brock wrote:
 Or we could simply not special case Proxy exotic objects and then Proxies 
 would be handled like any other object, the value of the objects 
 @@toStringTag property would be accessed and used to compose the toString 
 result.
 
 Which would result in things like [object ~Array]. That'd probably be 
 preferable than always returning [object Proxy] because at least you have 
 the option of special casing it if you desire. I don't know though, because a 
 Proxy for a Map would return [object Map], making it indistinguishable from 
 a map yet it's still just as useless as a Proxy for a Date.

Remember, O.p.toString is not a reliable brand test for anything other than 
built-ins that existed prior to ES6.  You should be trying to brand something 
defined via a proxy or any new built-in like Map.

 
 This just reminds me how cold I still am on the fact that you can't easily 
 one-off Proxy anything that's not a plain Object, Array, or Function because 
 of the lack of an invoke trap and every other type of built-in has private 
 state... but I suppose this isn't really the thread for that.

Right.  Deciding what we want for O.p.toString is a much simpler problem.

Allen
 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-11-01 Thread Brandon Benvie

On 11/1/2013 8:54 PM, Allen Wirfs-Brock wrote:

This just reminds me how cold I still am on the fact that you can't easily 
one-off Proxy anything that's not a plain Object, Array, or Function because of 
the lack of an invoke trap and every other type of built-in has private 
state... but I suppose this isn't really the thread for that.

Right.  Deciding what we want for O.p.toString is a much simpler problem.


I agree. I think the argument of what could possibly expect *either* a 
WeakMap or a Map is a convincing argument. The only place this breaks 
down is, of course, non-membrane Proxy usage. I'm willing to be 
convinced by a good use case where either a Map or WeakMap are 
interchangeable, but I don't think that exists.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Cross-global instanceof

2013-10-31 Thread Anne van Kesteren
This keeps coming up. Last instance:
http://mxr.mozilla.org/mozilla-central/source/dom/base/ObjectWrapper.jsm#16

We have it for Array using Array.isArray(). It is unclear why the
arguments for arrays not apply to other types of objects, such as
array buffers, nodes, blobs, files, etc.

We could introduce something like

  Object.crossGlobalInstanceOf(instance, type)

which checks @@crossGlobalBrand or some such which works for built-ins
and is also usable by jQuery and the like.


-- 
http://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread David Bruant

Le 31/10/2013 16:38, Anne van Kesteren a écrit :

This keeps coming up. Last instance:
http://mxr.mozilla.org/mozilla-central/source/dom/base/ObjectWrapper.jsm#16

We have it for Array using Array.isArray().

Array.isArray is not at all equivalent to instanceof. Not even related.
Object.create(Array.prototype) instanceof Array === true

var a = [];
a.__proto__ = null;
Array.isArray(a) === true;

We need both types of checks, one for is such object in the prototype 
chain? and the other for how is this object magic? (Array, Date, 
WeakMap, File, whatev's). The source code you're linking to seems to 
want the latter.



It is unclear why the
arguments for arrays not apply to other types of objects, such as
array buffers, nodes, blobs, files, etc.

We could introduce something like

   Object.crossGlobalInstanceOf(instance, type)

which checks @@crossGlobalBrand or some such which works for built-ins
and is also usable by jQuery and the like.
I'm not sure it's worth making it work for jQuery. This is trying to 
make a good use of same-origin multi-global which shouldn't exist in the 
first place. Keeping same-origin access as it is and encouraging people 
to add @sandbox even on same-origin iframes seems like a better idea.


Should the addition be a nicer Object.prototype.toString.call?

David
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread Brandon Benvie

On 10/31/2013 8:50 AM, David Bruant wrote:
I'm not sure it's worth making it work for jQuery. This is trying to 
make a good use of same-origin multi-global which shouldn't exist in 
the first place. Keeping same-origin access as it is and encouraging 
people to add @sandbox even on same-origin iframes seems like a better 
idea.


Should the addition be a nicer Object.prototype.toString.call?


You're right, it's not instanceof. But I definitely think the argument 
can be made that there is a need for checking if something is of a 
certain class. I'm finding myself wanting things like `isGenerator` and 
`isGeneratorFunction`, for example. There's countless examples of people 
re-purposing Object.prototype.toString to serve this functionality ad hoc.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread Allen Wirfs-Brock

On Oct 31, 2013, at 9:43 AM, Brandon Benvie wrote:

 On 10/31/2013 8:50 AM, David Bruant wrote:
 I'm not sure it's worth making it work for jQuery. This is trying to make a 
 good use of same-origin multi-global which shouldn't exist in the first 
 place. Keeping same-origin access as it is and encouraging people to add 
 @sandbox even on same-origin iframes seems like a better idea.
 
 Should the addition be a nicer Object.prototype.toString.call?
 
 You're right, it's not instanceof. But I definitely think the argument can be 
 made that there is a need for checking if something is of a certain class. 
 I'm finding myself wanting things like `isGenerator` and 
 `isGeneratorFunction`, for example. There's countless examples of people 
 re-purposing Object.prototype.toString to serve this functionality ad hoc.


What are the use cases for things like 'isGenerator'. When and why would you 
need to know that an object  upon which you are going to invoke the Iterator 
interface was/wasn't implemented by a generator.  If the reason is to know 
whether or not you can use the throw method (the only real difference between 
the generator object interface and the Iterator interface) you can test:
'throw' in possibleGenerator

In general this sort of isFoo or obj.constructor === Foo class test is a bad 
smell in dynamic class based languages and tends to be a reflection of static 
nominal type thinking (which is fine in its own context, but JS is has a 
dynamic class model).

Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread Andrea Giammarchi
I think the question is legit and this is a weak check

`'throw' in possibleGenerator`

specially if you have Dictionary like objects around ...

'length' in object does not tell you much, does it?

`Object.prototype.toString` is abused all over client/server
libraries/utilities since ducks sometimes might look like gooses too.

So eventually would you don't want developers to really know what they are
dealing with and promote weak feature detections instead? It might work,
but that ain't secure.

I still prefer `instanceof` for better performance since I don't usually
work with different realm but I also would like to have an
`Object.is(SomeClass, object);` facility instead of the boring, slow, and
inappropriate `{}.toString.call(obj)` check.

Just my thoughts, as usual.


On Thu, Oct 31, 2013 at 11:01 AM, Allen Wirfs-Brock
al...@wirfs-brock.comwrote:


 On Oct 31, 2013, at 9:43 AM, Brandon Benvie wrote:

  On 10/31/2013 8:50 AM, David Bruant wrote:
  I'm not sure it's worth making it work for jQuery. This is trying to
 make a good use of same-origin multi-global which shouldn't exist in the
 first place. Keeping same-origin access as it is and encouraging people to
 add @sandbox even on same-origin iframes seems like a better idea.
 
  Should the addition be a nicer Object.prototype.toString.call?
 
  You're right, it's not instanceof. But I definitely think the argument
 can be made that there is a need for checking if something is of a certain
 class. I'm finding myself wanting things like `isGenerator` and
 `isGeneratorFunction`, for example. There's countless examples of people
 re-purposing Object.prototype.toString to serve this functionality ad hoc.


 What are the use cases for things like 'isGenerator'. When and why would
 you need to know that an object  upon which you are going to invoke the
 Iterator interface was/wasn't implemented by a generator.  If the reason is
 to know whether or not you can use the throw method (the only real
 difference between the generator object interface and the Iterator
 interface) you can test:
 'throw' in possibleGenerator

 In general this sort of isFoo or obj.constructor === Foo class test is a
 bad smell in dynamic class based languages and tends to be a reflection of
 static nominal type thinking (which is fine in its own context, but JS is
 has a dynamic class model).

 Allen
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread Allen Wirfs-Brock

On Oct 31, 2013, at 1:58 PM, Andrea Giammarchi wrote:

 I think the question is legit and this is a weak check
 
 `'throw' in possibleGenerator`
 
 specially if you have Dictionary like objects around ...

And why would such an object be passed into a context where you expect to have 
a generator?  That would probably be an upstream bug and cause a downstream 
failure.  Presumably you should have tests that look for such failures.
 
 'length' in object does not tell you much, does it? 
 
who is that relevant?  If you need to condition something on the existence of a 
length property, you can.  But in most situations you don't want to do such 
tests.  Just access the property and use it/call it.  It it is the right kind 
of object things will work.  If it is the wrong kind, it is somebody's bug.  
 `Object.prototype.toString` is abused all over client/server 
 libraries/utilities since ducks sometimes might look like gooses too.

Any, quite likely, most commonly used for unnecessary nominal type tests.

 So eventually would you don't want developers to really know what they are 
 dealing with and promote weak feature detections instead? It might work, but 
 that ain't secure.

Yes, no. Good OO is about letting go of knowledge of an objects implementation. 
 In most cases you should only be concerned about the object behavior you will 
use and not care about who implemented it or how or whether or not there are 
multiple interoperable implementations operating.  But you should be feature 
testing for the behavior you depend upon.  Just invoke it.  It the method need 
isn't there you are usually going to get an exception, typically sooner that 
latter.   Feature detection shouldn't be  used as poor-man nominal type 
checking (where you throw if it fails).  You should only use feature checking, 
when you have real alternative paths to take depending upon the presence of the 
feature. 

Secure?  What kind of security for what purpose? Every little about JS is 
secure.

Of course, there really are some places where you really do need to do a brand 
check for a specific object implementation.   In those cases, the 
implementation of the object should include brand checking in its design and 
expose an appropriate function for doing the check.  But a general purpose 
mechanism is an attractive nuisance, and probably doesn't actually do the check 
you need for your specific use case.

 
 I still prefer `instanceof` for better performance since I don't usually work 
 with different realm but I also would like to have an `Object.is(SomeClass, 
 object);` facility instead of the boring, slow, and inappropriate 
 `{}.toString.call(obj)` check.

Show me real use cases and I'll try to explain with the check isn't needed.

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cross-global instanceof

2013-10-31 Thread Allen Wirfs-Brock

On Oct 31, 2013, at 2:56 PM, Andrea Giammarchi wrote:

 Sorry, secure was actually reliable, as being secure about the type, not 
 about security itself.
 
 A case where I do use instanceof is, example, with new String to easily 
 decide later on what to do with such object that should not be treated as 
 such.
 
 The script does resolve circular dependencies backward and forward out of 
 JSON.stringiy and JSON.parse that do create objects from the current realm.
 
 Nothing else than `instanceof` is as usable/useful in current ESX spec for 
 same purpose in terms of performance and reliability.
 
 https://github.com/WebReflection/circular-json/blob/master/src/circular-json.js#L108
 
 Just one case, still `instanceof` is used a lot and usually for good reasons, 
 ...

Well I promised I'd explain how I'd eliminate use of 'instanceof' so here goes. 
Note that since this is in the context of talking about possible ES extensions 
I'll assume those are available.

First, you're using (lines 20) String wrapper objects(with the name String 
aliased to $String)  to pass around string values that require special 
processing.  Personally, I find this a little too subtle.  In ES6 I'd do this 
way instead:

const isSpecialString = Symbol.for(isSpecialString);  //registration proposal 
in http://esdiscuss.org/topic/comments-on-sept-meeting-notes#content-76 
class SpecialString extends String {
   constructor(str) {
   super(str.slice(1)) //move string preprocessing into constructor
   }
   [isSpecialString]() {return isSpecialString in this};  //not really intended 
to be called
}

In line 110 I'd use
Array.isArray(current) 
instead of 
current instanceof Array 
(note that JSON processing was one of the original use cases that motivated 
Array.isArray)

In line 114, instead of
 current instanceof $String ?
i'd use
 isSpecialString in  current ?//note works cross-realm, if that is what is 
desired. 

I may be missing something WRT possible cross-realm issues, but in line 126 I'd 
replace
   current instanceof Object
with
   typeof current ==  'object'
but, I'm really thinking that I must be missing something that motivated your 
use of instanceof.  Is the supposed to be a Realm check?

 ... not because we are all bad developers (I hope ...)

No, but possibly developers who learned (or were taught be people who learned) 
about such things in a language context where static nominal class tests make 
more sense.

Allen




 
 Cheers
 
 
 
 On Thu, Oct 31, 2013 at 2:32 PM, Allen Wirfs-Brock al...@wirfs-brock.com 
 wrote:
 
 On Oct 31, 2013, at 1:58 PM, Andrea Giammarchi wrote:
 
 I think the question is legit and this is a weak check
 
 `'throw' in possibleGenerator`
 
 specially if you have Dictionary like objects around ...
 
 And why would such an object be passed into a context where you expect to 
 have a generator?  That would probably be an upstream bug and cause a 
 downstream failure.  Presumably you should have tests that look for such 
 failures.
 
 'length' in object does not tell you much, does it? 
 
 
 who is that relevant?  If you need to condition something on the existence of 
 a length property, you can.  But in most situations you don't want to do such 
 tests.  Just access the property and use it/call it.  It it is the right kind 
 of object things will work.  If it is the wrong kind, it is somebody's bug.  
 `Object.prototype.toString` is abused all over client/server 
 libraries/utilities since ducks sometimes might look like gooses too.
 
 Any, quite likely, most commonly used for unnecessary nominal type tests.
 
 So eventually would you don't want developers to really know what they are 
 dealing with and promote weak feature detections instead? It might work, but 
 that ain't secure.
 
 Yes, no. Good OO is about letting go of knowledge of an objects 
 implementation.  In most cases you should only be concerned about the object 
 behavior you will use and not care about who implemented it or how or whether 
 or not there are multiple interoperable implementations operating.  But you 
 should be feature testing for the behavior you depend upon.  Just invoke it.  
 It the method need isn't there you are usually going to get an exception, 
 typically sooner that latter.   Feature detection shouldn't be  used as 
 poor-man nominal type checking (where you throw if it fails).  You should 
 only use feature checking, when you have real alternative paths to take 
 depending upon the presence of the feature. 
 
 Secure?  What kind of security for what purpose? Every little about JS is 
 secure.
 
 Of course, there really are some places where you really do need to do a 
 brand check for a specific object implementation.   In those cases, the 
 implementation of the object should include brand checking in its design and 
 expose an appropriate function for doing the check.  But a general purpose 
 mechanism is an attractive nuisance, and probably doesn't actually do the 
 check you need for 

Re: Cross-global instanceof

2013-10-31 Thread Andrea Giammarchi
Allen, in which place on current known universe, when you parse a
JSON.string, your reviver function receives objects from another realm,
exactly?

That logic is bypassing and full-satisfying JSON.parse revival expectations
returning object later on checked as instanceof String in order to
differentiate and revive them differently and the same is done for Object,
where `typeof` would create a disaster in that tested logic with just a
`null` value plus CircularJSON is fully compatible with ES3 and Mr D.
Crockford JSON polyfill too so   since we'd like to have shimmable code
and Symbols are a no-go, do you still think instanceof is not needed at all?

'cause just this `null instanceof Object` is a good reason to use it when
objects are expected in a revival loop, imho.

Thanks, regardless, for spending some time on it.

Cheers


On Thu, Oct 31, 2013 at 5:50 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:


 On Oct 31, 2013, at 2:56 PM, Andrea Giammarchi wrote:

 Sorry, secure was actually reliable, as being secure about the type, not
 about security itself.

 A case where I do use instanceof is, example, with new String to easily
 decide later on what to do with such object that should not be treated as
 such.

 The script does resolve circular dependencies backward and forward out of
 JSON.stringiy and JSON.parse that do create objects from the current realm.

 Nothing else than `instanceof` is as usable/useful in current ESX spec for
 same purpose in terms of performance and reliability.


 https://github.com/WebReflection/circular-json/blob/master/src/circular-json.js#L108

 Just one case, still `instanceof` is used a lot and usually for good
 reasons, ...


 Well I promised I'd explain how I'd eliminate use of 'instanceof' so here
 goes. Note that since this is in the context of talking about possible ES
 extensions I'll assume those are available.

 First, you're using (lines 20) String wrapper objects(with the name String
 aliased to $String)  to pass around string values that require special
 processing.  Personally, I find this a little too subtle.  In ES6 I'd do
 this way instead:

 const isSpecialString = Symbol.for(isSpecialString);  //registration
 proposal in
 http://esdiscuss.org/topic/comments-on-sept-meeting-notes#content-76
 class SpecialString extends String {
constructor(str) {
super(str.slice(1)) //move string preprocessing into constructor
}
[isSpecialString]() {return isSpecialString in this};  //not really
 intended to be called
 }

 In line 110 I'd use
 Array.isArray(current)
 instead of
 current instanceof Array
 (note that JSON processing was one of the original use cases that
 motivated Array.isArray)

 In line 114, instead of
  current instanceof $String ?
 i'd use
  isSpecialString in  current ?//note works cross-realm, if that is
 what is desired.

 I may be missing something WRT possible cross-realm issues, but in line
 126 I'd replace
current instanceof Object
 with
typeof current ==  'object'
 but, I'm really thinking that I must be missing something that motivated
 your use of instanceof.  Is the supposed to be a Realm check?

 ... not because we are all bad developers (I hope ...)


 No, but possibly developers who learned (or were taught be people who
 learned) about such things in a language context where static nominal class
 tests make more sense.

 Allen





 Cheers



 On Thu, Oct 31, 2013 at 2:32 PM, Allen Wirfs-Brock 
 al...@wirfs-brock.comwrote:


 On Oct 31, 2013, at 1:58 PM, Andrea Giammarchi wrote:

 I think the question is legit and this is a weak check

 `'throw' in possibleGenerator`

 specially if you have Dictionary like objects around ...


 And why would such an object be passed into a context where you expect to
 have a generator?  That would probably be an upstream bug and cause a
 downstream failure.  Presumably you should have tests that look for such
 failures.


 'length' in object does not tell you much, does it?

 who is that relevant?  If you need to condition something on the
 existence of a length property, you can.  But in most situations you don't
 want to do such tests.  Just access the property and use it/call it.  It it
 is the right kind of object things will work.  If it is the wrong kind, it
 is somebody's bug.

 `Object.prototype.toString` is abused all over client/server
 libraries/utilities since ducks sometimes might look like gooses too.


 Any, quite likely, most commonly used for unnecessary nominal type tests.

 So eventually would you don't want developers to really know what they
 are dealing with and promote weak feature detections instead? It might
 work, but that ain't secure.


 Yes, no. Good OO is about letting go of knowledge of an objects
 implementation.  In most cases you should only be concerned about the
 object behavior you will use and not care about who implemented it or how
 or whether or not there are multiple interoperable implementations
 operating.  But you 

Re: Cross-global instanceof

2013-10-31 Thread Oliver Hunt

On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi andrea.giammar...@gmail.com 
wrote:

 Allen, in which place on current known universe, when you parse a 
 JSON.string, your reviver function receives objects from another realm, 
 exactly?
Please try to keep the discourse polite.

That said this is fairly trivial

realm a
function reviver(…) { … }
/

realm b
JSON.parse(… realm a.reviver …)
/

now the realm of the objects created by the JSON object differ from the realm 
that the reviver function is working in.

—Oliver



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss