Cross-global instanceof

# Anne van Kesteren (11 years ago)

This keeps coming up. Last instance: 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.

# David Bruant (11 years ago)

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

This keeps coming up. Last instance: 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?

# Brandon Benvie (11 years ago)

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.

# Allen Wirfs-Brock (11 years ago)

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).

# Andrea Giammarchi (11 years ago)

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.

# Allen Wirfs-Brock (11 years ago)

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.

# Andrea Giammarchi (11 years ago)

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.

WebReflection/circular-json/blob/master/src/circular-json.js#L108

Just one case, still instanceof is used a lot and usually for good reasons, not because we are all bad developers (I hope ...)

# Allen Wirfs-Brock (11 years ago)

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

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.

# Andrea Giammarchi (11 years ago)

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.

# Oliver Hunt (11 years ago)

On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi <andrea.giammarchi at 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.

# Andrea Giammarchi (11 years ago)

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

# Andrea Giammarchi (11 years ago)

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!

# Oliver Hunt (11 years ago)

On Nov 1, 2013, at 7:23 PM, Andrea Giammarchi <andrea.giammarchi at 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

# Andrea Giammarchi (11 years ago)

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.

# Anne van Kesteren (11 years ago)

On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock <allen at 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.

# Allen Wirfs-Brock (11 years ago)

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

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.

# Andrea Giammarchi (11 years ago)

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.

# Mark S. Miller (11 years ago)

On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

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.

# Andrea Giammarchi (11 years ago)

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

# Mark S. Miller (11 years ago)

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.

# Mark Miller (11 years ago)
# Allen Wirfs-Brock (11 years ago)

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 Wirfs-Brock (11 years ago)

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}
}
# Mark S. Miller (11 years ago)

On Fri, Nov 1, 2013 at 4:03 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

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?

# Brandon Benvie (11 years ago)

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.'

# Mark S. Miller (11 years ago)

I just read 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!

# Brandon Benvie (11 years ago)

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...

# Brandon Benvie (11 years ago)

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

# David Bruant (11 years ago)

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.

# Allen Wirfs-Brock (11 years ago)

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

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'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.

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.

# Brandon Benvie (11 years ago)

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.

# Allen Wirfs-Brock (11 years ago)

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.

# Brandon Benvie (11 years ago)

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.

# Jake Verbaten (11 years ago)

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 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 ( visionmedia/co/blob/master/index.js#L153 ).

I also personally use an isGenerator function ( 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

# David Bruant (11 years ago)

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?

# Allen Wirfs-Brock (11 years ago)

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

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.

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, esdiscuss/2011-July/015935 ) 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.

# Mark S. Miller (11 years ago)

On Sat, Nov 2, 2013 at 10:55 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

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

not?

# Allen Wirfs-Brock (11 years ago)

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

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

not?

shouldn't