Kevin Smith <mailto:[email protected]>
September 26, 2013 6:11 AM
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?
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.
- 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).
- Since it is just a string, it requires no changes to property
semantics, and it trivially works across realms.
{ Kevin }
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
Kevin Smith <mailto:[email protected]>
September 25, 2013 11:53 AM
I think that your example _might_ do it, although I'll have to think
more about it tonight.
If so, then the justification for symbols at this point is based on
the dual use of JS objects as programming abstractions and as a
key-value data structure. Oh, javascript... : )
{ Kevin }
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
Domenic Denicola <mailto:[email protected]>
September 25, 2013 11:41 AM
From: Kevin Smith [[email protected]]
I'm still not quite convinced that objects-as-maps make a truly isolated
namespace necessary, however. I would be convinced by a code example showing
how a property of an object using arbitrary string keys could be misinterpreted
as a meta-level property.
I'll try to think of one...
The hard part of producing such examples is that most of the meta-level
properties are functions (e.g. iterator), and thus it's not trivially easy to
produce an object from `JSON.parse`ing user input. But there are some
meta-level properties that are not functions, namely @@isRegExp, @@toStringTag,
and @@unscopables.
So let's say that we decided to use a non-isolated namespace of strings, instead of unique symbols. Thus, we
would have `"std:isRegExp"`, `"std:toStringTag"`, and `"std:unscopeables"`.
Well, then simple code like this:
```js
var requestBody = JSON.parse(req.body);
```
could end up getting a very weird object, if I POSTed the string
```
{
"std:isRegExp": true,
"std:toStringTag": "My Custom String Tag With Spaces and Punctuation!",
"std:unscopeables": ["hasOwnProperty", "toString", "propertyIsEnumerable"]
}
```
to that HTTP endpoint.
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
Kevin Smith <mailto:[email protected]>
September 25, 2013 11:34 AM
Thanks, Domenic. I withdraw that aspect of the argument.
I'm still not quite convinced that objects-as-maps make a truly
isolated namespace necessary, however. I would be convinced by a code
example showing how a property of an object using arbitrary string
keys could be misinterpreted as a meta-level property.
I'll try to think of one...
{ Kevin }
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
Domenic Denicola <mailto:[email protected]>
September 24, 2013 9:40 PM
I do not plan to switch to Map for string-keyed maps. I’ll be using
`Object.create(null)` instead.
*From:*es-discuss [mailto:[email protected]] *On Behalf
Of *Kevin Smith
*Sent:* Wednesday, September 25, 2013 00:05
*To:* Tab Atkins Jr.
*Cc:* es-discuss
*Subject:* Re: Comments on Sept Meeting Notes
This seems like a non-sequitur. Symbols aren't meant to help with the
"object as map" use-case, and even if you tried to, they work terribly
for it. They're meant for the "add an actual property/method without
collision" use-case. Again, Maps seem like a non-sequitur here -
using a Map doesn't aid with avoiding collisions.
Before Maps, I might use a regular object to store arbitrary
string-to-value mappings. Say I'm counting the occurrences of terms
appearing on es-discuss. The key "std:iterator" might actually occur.
In that case we would have a collision with my proposed meta-level
property name. But going forward, no one's going to use a regular
object for arbitrary string keys - it's simply too error-prone.
They'll use a Map instead. Which means that we don't have to worry
about arbitrary string keys colliding with meta-level property names.
Now, one might argue that using the string "std:iterator" (or
equivalent) would present a backward compatibility hazard for legacy
code using objects as maps. I'll have to think about that one...
The argument is that, once you take out arbitrary string keys (as
occur when using an object as map), a "namespaced" string provides
sufficient collision resistance to make symbols unnecessary.
How is this in any way better than:
class C {
std_iterator() { ... }
}
The set of non-identifiers is less commonly used for member names by
far, so it has that advantage. But I'm not really saying that
"std:iterator" is better than "std_iterator". I'm saying that both are
a simpler solution than symbols.
{ Kevin }
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss