Rick Waldron (2013-09-26T21:01:35.000Z)
On Thu, Sep 26, 2013 at 9:11 AM, Kevin Smith <zenparsing at gmail.com> wrote:

> After thinking this over, I still remain unconvinced that symbols are the
> right solution to the problem.  Besides the fact that they introduce (ever
> more) complexity to the object model, they simply do not work as a
> duck-typing strategy for the real, *multi-realm* world of Javascript.
>  Sure, we can make a special case of standard library symbols such that
> they maintain identity across realms.  But a solution which only works for
> special cases isn't a very good solution, is it?
>

The consensus included Allen writing proposal for user-defined well-known
symbol registration—these symbols would also maintain identity across
realms.

https://github.com/rwaldron/tc39-notes/blob/master/es6/2013-09/sept-18.md#consensusresolution-1


> Here is another proposal which avoids these pitfalls:
>
> 1) Identify all meta-layer hooks using a string that is not an identifier.
>  The actual string used doesn't matter in this proposal, but for
> illustration purposes I'll use an "@"-prefix.
>
> 2) Define all meta-layer hooks as functions.  Testing for the hook will
> involve [[Get]] followed by [[IsCallable]].
>
> For example, defining an iterable:
>
>     class C { "@iterator"(...args) { /* ... */ } }
>
>  Overriding the string tag:
>
>     class C { "@toStringTag"() { return "[object C]"; } }
>
> - Since the property name is a non-identifer, it is unlikely to collide
> with any object members.
>

But these can still easily collide with <identifier-name-string> property
access (of the same string name), so I don't understand how this is better,
can you clarify?


- Since the value of the hook must be a function, it is unlikely to collide
> with keys in an object-as-map (e.g. a JSON object).
>

What about something like this?

// event.js
let events = Symbol();

export class Emitter {
  constructor() {
    this[events] = Object.create(null);
  }
  on(type, handler) {...},
  off(type, handler) {...}
  emit(type, ...args) {...}
}

// program.js
import { Emitter } from "event";

class Serialport extends Emitter {
  constructor() {
    super();

    // there is no way to accidentally pave
    // over the `events` symbol property
  }
}


If I try that with your proposal:


// event.js
export class Emitter {
  constructor() {
    this["@events"] = Object.create(null);
  }
  on(type, handler) {...},
  off(type, handler) {...}
  emit(type, ...args) {...}
}

// program.js
import { Emitter } from "Event";

class Serialport extends Emitter {
  constructor() {
    super();

    this["@events"] = "MINE";
  }
}



Rick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130926/9440213f/attachment.html>
domenic at domenicdenicola.com (2013-10-13T02:27:38.591Z)
On Thu, Sep 26, 2013 at 9:11 AM, Kevin Smith <zenparsing at gmail.com> wrote:

> After thinking this over, I still remain unconvinced that symbols are the
> right solution to the problem.  Besides the fact that they introduce (ever
> more) complexity to the object model, they simply do not work as a
> duck-typing strategy for the real, *multi-realm* world of Javascript.
>  Sure, we can make a special case of standard library symbols such that
> they maintain identity across realms.  But a solution which only works for
> special cases isn't a very good solution, is it?
>

The consensus included Allen writing proposal for user-defined well-known
symbol registration—these symbols would also maintain identity across
realms.

https://github.com/rwaldron/tc39-notes/blob/master/es6/2013-09/sept-18.md#consensusresolution-1


> Here is another proposal which avoids these pitfalls:
>
> 1) Identify all meta-layer hooks using a string that is not an identifier.
>  The actual string used doesn't matter in this proposal, but for
> illustration purposes I'll use an "@"-prefix.
>
> 2) Define all meta-layer hooks as functions.  Testing for the hook will
> involve [[Get]] followed by [[IsCallable]].
>
> For example, defining an iterable:
>
>     class C { "@iterator"(...args) { /* ... */ } }
>
>  Overriding the string tag:
>
>     class C { "@toStringTag"() { return "[object C]"; } }
>
> - Since the property name is a non-identifer, it is unlikely to collide
> with any object members.
>

But these can still easily collide with <identifier-name-string> property access (of the same string name), so I don't understand how this is better, can you clarify?


- Since the value of the hook must be a function, it is unlikely to collide
> with keys in an object-as-map (e.g. a JSON object).
>

What about something like this?

```js
// event.js
let events = Symbol();

export class Emitter {
  constructor() {
    this[events] = Object.create(null);
  }
  on(type, handler) {...},
  off(type, handler) {...}
  emit(type, ...args) {...}
}

// program.js
import { Emitter } from "event";

class Serialport extends Emitter {
  constructor() {
    super();

    // there is no way to accidentally pave
    // over the `events` symbol property
  }
}
```

If I try that with your proposal:

```js
// event.js
export class Emitter {
  constructor() {
    this["@events"] = Object.create(null);
  }
  on(type, handler) {...},
  off(type, handler) {...}
  emit(type, ...args) {...}
}

// program.js
import { Emitter } from "Event";

class Serialport extends Emitter {
  constructor() {
    super();

    this["@events"] = "MINE";
  }
}
```