Exporting Symbols

Dean Landolt dean at deanlandolt.com
Fri Oct 16 21:14:02 UTC 2015

On Fri, Oct 16, 2015 at 3:46 PM, Rick Waldron <waldron.rick at gmail.com>

> On Fri, Oct 16, 2015 at 2:47 PM Dean Landolt <dean at deanlandolt.com> wrote:
>> The symbol registry is a great way to map universal (not just global, but
>> fully cross-realm) names (strings) to unique, distinct concepts (symbols).
>> But as a flat string namespace has all the same kinds of issues symbols
>> were introduced to solve. IIUC throwing `Math.random` strings into the
>> symbol registry is pretty much equivalent to writing (non-enumerable)
>> Math.random object properties on the global object, right?
> Global object is not cross-realm. Symbol registry is cross realm, try this
>   var iframe = document.createElement("iframe");
>   document.body.appendChild(iframe);
>   iframe.contentWindow.Symbol.iterator === Symbol.iterator; // true, this
> is in the Symbol registry.
>   iframe.contentWindow.Symbol === Symbol; // false
>   iframe.contentWindow.Array === Array; // false

I know -- I said that in the first line of my message :)

But if you register a random value as the key of a symbol, how would a
consumer resolve that key? They would have to get a reference to the
module, right? How would two different consumers, in two different realms,
resolve the same key? AFAIK they can't, at least not without additional
coordination. AFAIK this symbol would only be useful to users within a
single realm, which is why I suggested it was equivalent to tucking it on a
global somewhere.

> Also, the OP is actually asking to give away the Symbol key:
>   "There are special features we want to expose if a module defines a
> certain key. However, we’d like to not rely on certain names just because
> there’s some chance they came up with it themselves. If it was a symbol
> that we gave them access to, it would be impossible for this to be the
> case, they would have had to grab the symbol from us:
>   var SpecialSymbol = require(“our-symbols”).SpecialSymbol;
>   export { whatever as SpecialSymbol }"
> My example wasn't intended to show Francisco what I think he _should_ do,
> just to answer his question based on his expressed parameters.

Fair enough -- I wasn't trying to call out your answer specifically -- I
was just trying to point out the benefits using the symbol registry for
truly cross-realm coordination, and trying to expand a bit on what that can
look like.

Francisco's examples, from what I could tell at least, can't really be made
to work as is, even if you could export symbol bindings. The symbols being
exported are generated within the module itself, so without associating
them with some known semantics (one way or another), they're completely
opaque to downstream consumers. When default-exporting an object w/ symbol
keys, you can get a handle on all these symbols through reflection, but
they're still inherently indistinguishable from each other, and meaningless
in general. (Unless you switch on their string description -- but that's

The solution you proposed does accomplish what he seems to be after -- but
I suppose I neglected to elaborate on why I believe what he's chasing is
fundamentally flawed...

> If it were me...
>   // module.js
>   let sym = Symbol();
>   // ...use my sym for special features...
>   export { sym as feature }
> Seems sufficient? Maybe I've misunderstood the constraints.

IIUC he wants to export multiple symbols from a given module, without
having to conjure up application-specific strings for each. But as soon as
you introduce objects with opaque identity (what a philosopher might call
"intensional objects") -- whether through Symbols, UUIDs, random values,
whatever -- you have to come up with some mechanism to communicate their
semantics. Otherwise they're completely useless, for identity purposes at
least. Unless they fail at being opaque -- but that's always a bug...

For example, Symbols themselves are beautifully opaque -- but if you try to
use the Symbol description string as a means to communicate semantics on a
symbol instance you break this property. Don't do that. It may seem as
though something like a UUIDv1, which exposes process identity and some
information about the processor's wallclock, isn't fully opaque. This
information can be used to partially order the creation date of UUIDs by
the process which generated them, but this says absolutely nothing about
what any of these UUIDs actually represent. From an identity standpoint,
they're still completely opaque.

So if you export an opaque identity that you created yourself, and don't
expose some mechanism for downstream consumers to know what it means,
you're handing a bag of meaningless tokens which are, by definition,
completely useless to them.

This problem of assigning semantics is neatly solved by the symbol registry
-- and IMHO can be solved properly by using something like fully qualified
uris as keys in the symbol registry. Any global namespace will do -- DNS,
namecoin, any PKI infrastructure, etc., so long as it has a uri scheme you
naturally get a string-prefixed subspace of the symbol registry you can do
whatever the hell you want with.

To export these symbols directly from his library, Fransisco would still
have to associate them with string keys of his choosing -- which seems like
the core problem he was hoping to solve with symbols. I'm arguing that
unless you're the only one using a symbol you create, you have to conjure
up some mechanism of communicating its semantics to other users -- symbols
can't solve this problem alone.

All that said, I can see the benefit to being able to export symbol
bindings, which was the main point of his message -- at least registered
symbols. Perhaps we just need to grow some syntax for creating registered
symbols which is statically analyzable to make this feasible?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151016/1a01e27a/attachment.html>

More information about the es-discuss mailing list