A random collection of ES4 draft spec surprises and thoughts

# Mark S. Miller (16 years ago)

In going over the ES4 draft spec docs, I found the following things surprising:

Grammar

  • The BOM sequence shall be "replaced with a single white space character". Which one? Should we say instead "treated as a single whitespace character"?

  • What's __proto__ doing in the grammar? If we want to provide access to the internal [[Prototype]] property (as I think we do), we should do that explicitly with a reflective operation such as Object.prototypeOf(obj). But please let's avoid turning this internal property into a named property. Doing so breaks the subset relationship between JSON and EcmaScript. (Granted, we also need to acknowledge that this relationship is currently broken by Firefox. But part of the purpose of standards is to encourage browser vendors to repair their implementations.)

  • What's >==? I've never seen that before.

  • What does the var attribute mean inside an object literal?

  • Now that we have let-at-the-new-var, i.e., a properly lexically scoped letrec behavior, do we still need the "let" expression and the "let" comprehension? Can we kill these?

  • Why does the grammar allow function calls in LeftHandSideExpressions. For example, what's the meaning of:

    foo(a)++
    
  • Why does delete operate on a PostFixExpression rather than a LeftHandSideExpression? What's the meaning of:

    delete x++;
    
  • I thought like was dead. How did it get revived?

  • What is

    "super" "(" Arguments ")"
    

    Last I heard, ES4 only has single implementation inheritance, so why allow "super" to be qualified?

Core Semantics

  • I'm pleasantly surprised to see that the prototype reference (which I take to be the same as the ES3 internal [[Prototype]] property) is said to be immutable. Does this mean that we will be able to consider the following behavior buggy (I hope so):

    var x = {};
    
    var y = {};
    
    x.__proto__ = y;
    [object Object]
    
    y.foo = 3;
    3
    
    x.foo
    3
    
  • What namespace is __ES4__ defined in? The text "The namespace __ES4__ is predefined. It is used to tag global names that have been introduced in the 4th edition" would seem to indicate that __ES4__ is itself defined in the namespace __ES4__. I'm probably missing or confused about something.

  • Unicode only has 21 bits of significance. That's enough headroom that we should expect Unicode to live within these limits until the United Federation of Planets makes peace with the Romulans and the Klingons. So why is a string value defined as "a finite ordered sequence of zero or more 32 bit unsigned integer values"?

  • What does "Rib" mean? Is it an acronym?

  • Is "A catch-all method operates on the object that contains the method." a mistake? Did you mean "operates on the invoked object"?

# Mike Shaver (16 years ago)

On Mon, May 26, 2008 at 2:06 PM, Mark S. Miller <erights at google.com> wrote:

  • What's >==? I've never seen that before.

I presume it's >= but with no type coercion".

# Graydon Hoare (16 years ago)

Mark S. Miller wrote:

In going over the ES4 draft spec docs, I found the following things surprising:

I can't answer all of these, but can a few. Most of the grammar questions are outside of things I know.

  • I thought like was dead. How did it get revived?

As a (value * type) binary operator, rather than as a type. It also (presently) has a form in which it can annotate a function parameter, which implicitly causes the an assertion of the operator against the provided type when the function is entered. This annotation behavior on function parameter lists is something I'm not terribly pleased with, but then, the most natural boundary between annotated and unannotated code appears to be that of a function call, so it's possibly sensible to leave extra conveniences there.

  • What is

     "super" "(" Arguments ")"
    

    Last I heard, ES4 only has single implementation inheritance, so why allow "super" to be qualified?

I don't know what you mean by qualified. That's a form for either constructor-chaining or dispatching to a parent method with the same name as the current method.

  • I'm pleasantly surprised to see that the prototype reference (which I take to be the same as the ES3 internal [[Prototype]] property) is said to be immutable. Does this mean that we will be able to consider the following behavior buggy (I hope so):

Yes.

  • What namespace is __ES4__ defined in? The text "The namespace __ES4__ is predefined. It is used to tag global names that have been introduced in the 4th edition" would seem to indicate that __ES4__ is itself defined in the namespace __ES4__. I'm probably missing or confused about something.

Sorry about this. There was text in the section on names that clarified the root namespace bindings but it appears to have been cut during some rewriting. I'll try to ensure it shows up again.

At the moment the ES4 namespace is visible as the global property __ES4__ to 3rd edition code, because it is bound to the global name ""::__ES4__ and 3rd edition code has the transparent public namespace "" open in its root scope. This is the "backwards compatibility hazard" if some 3rd edition code happens to accidentally wish to reuse the global variable __ES4__.

All other names introduced are qualified by the ES4 namespace, or by namespaces that are themselves qualified by the ES4 namespace (including things like the "public" synonym for the transparent public namespace; that's actually bound to __ES4__::public). So 3rd edition code is not going to collide with such names, since 3rd edition code is never going to contain a name expression __ES4__::foo that would be necessary to start digging around in that namespace.

The ES4 namespace is open in the root scope of any 4th edition code. You're right that we could possibly get away with only binding the ES4 namespace to, essentially, <ES4>::__ES4__, where <ES4> is the opaque

namespace object itself. We don't do that at present, but we've tried to keep any name pollution to a minimum so this might be a desirable final touch if we can make it work.

  • Unicode only has 21 bits of significance. That's enough headroom that we should expect Unicode to live within these limits until the United Federation of Planets makes peace with the Romulans and the Klingons. So why is a string value defined as "a finite ordered sequence of zero or more 32 bit unsigned integer values"?

Because a string value in the 3rd edition is defined as "a finite ordered sequence of zero or more 16 bit unsigned integer values". Emphatically not as a unicode string. Unicode strings are a useful subset of what a 3rd edition string value can hold, but they're not defined that way. In particular, the private surrogate range is totally fair game in 3rd edition implementations. The expansion to 32 bits is simply a matter of utility: it's much more useful in general to have a dense u32 sequence than a dense u21 sequence.

  • What does "Rib" mean? Is it an acronym?

Not an acronym. A rib is a (name -> fixture) binding map. It defines the

set of fixed properties that will exist in a scope or an instance.

There is some redundancy between ribs and non-value property states, in the present RI. I'm in the process of eliminating this redundancy in favour of relying on ribs directly, and using properties only to model what's now called the value state.

# Jason Orendorff (16 years ago)

I can answer two more :)

On Mon, May 26, 2008 at 1:06 PM, Mark S. Miller <erights at google.com> wrote:

  • What does the var attribute mean inside an object literal?

See Lars's "ES4 stable draft: Object initializers": mail.mozilla.org/pipermail/es4-discuss/2008-April/002668.html

  • Why does the grammar allow function calls in LeftHandSideExpressions. For example, what's the meaning of

     foo(a)++
    

As far as I know, this is unchanged from ES3, in which "functions are permitted to return References" but "This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference.": bclary.com/2004/11/07/#a-8.7 and an implementation that doesn't hold with such nonsense is also allowed to reject foo(a)++ as a syntax error: bclary.com/2004/11/07/#a

# Brendan Eich (16 years ago)

On May 26, 2008, at 11:06 AM, Mark S. Miller wrote:

Doing so breaks the subset relationship between JSON and EcmaScript. (Granted, we also need to acknowledge that this relationship is currently broken by Firefox.

Not Firefox -- both Mozilla JS implementations (SpiderMonkey and
Rhino) support proto (readably -- let's ignore the writable case).

ActionScript also had read-only proto in at least one of its
versions. I'm not sure if it still does in AS3.

But part of the purpose of standards is to encourage browser vendors to repair their implementations.)

If it ain't broke, don't fix it.

If I recall correctly (and I'm sure someone will set me straight
otherwise), JSON is not compatible with ES3 -- Unicode non-BMP
character handling differs. Trying to force a subset relation from
JSON to ES4 is not going to fly if JSON is not a subset of ES3. What
matters is the intersection being "big enough", and hard cases like
proto or other mangled names do not much matter.

  • What's ">=="? I've never seen that before.

A typo?

  • What does the "var" attribute mean inside an object literal?

Same as elsewhere: it makes a fixture.

  • Now that we have let-at-the-new-var, i.e., a properly lexically scoped letrec behavior, do we still need the "let" expression and the "let" comprehension? Can we kill these?

(I'm not sure what you mean by "let" comprehension, but :) No, they
have different use-cases that deserve attention.

  • Why does the grammar allow function calls in LeftHandSideExpressions. For example, what's the meaning of

    foo(a)++

?

Notice how ES1-3 grammars also produced such sentences. We do not use
a bottom-up grammar to make such sentences not parse, and neither do
real implementations.

Indeed, IE JScript (for VBScript compatibility) long ago added
support for "Reference" type return values from certain native ("host
object") methods. This enabled domNode.item(i) = j, e.g. SpiderMonkey
added support because someone embedding its open source wanted to
support code written for JScript.

Thus the ES1-4 grammars can produce these expressions, but they are
ruled out semantically for some or all kinds of objects. See ES3
11.3.1 and 11.13.1, then 8.7.1 step 1; also 16 fourth bulleted item.

  • Why does delete operate on a PostFixExpression rather than a LeftHandSideExpression? What's the meaning of

    delete x++;

?

This looks like a bug to me: ES3 has the production

UnaryExpression : delete UnaryExpression

But in any case, LeftHandSideExpression is not compatible. Jeff
should weigh in here.

  • I thought "like" was dead. How did it get revived?

We removed "like" from the type system. It's still a binary operator,
and there is sugar for enforcing like relations on arguments and
return values.

  • What is

    "super" "(" Arguments ")"

? Last I heard, ES4 only has single implementation inheritance, so why allow "super" to be qualified?

Not sure what you mean by "qualified", but super can be called.

       Core Semantics
  • I'm pleasantly surprised to see that the prototype reference (which I take to be the same as the ES3 internal [[Prototype]] property) is said to be immutable. Does this mean that we will be able to consider the following behavior buggy (I hope so):

    var x = {};

    var y = {};

    x.proto = y; [object Object]

    y.foo = 3; 3

    x.foo 3

If the property is read-only then of course assignment to a property
of y can't affect x. Under 'use strict', the attempt to set the read- only proto property throws.

  • What namespace is "ES4" defined in?

The public (compatibility) one -- hence the ugly __ bracketing, to
minimize chance of collision.

I left a few questions for others to answer ("rib" is defined in at
least one place in the draft specs I reviewed).

# Brendan Eich (16 years ago)

On May 26, 2008, at 11:57 AM, Graydon Hoare wrote:

  • I thought "like" was dead. How did it get revived?

As a (value * type) binary operator, rather than as a type. It also (presently) has a form in which it can annotate a function parameter, which implicitly causes the an assertion of the operator against the provided type when the function is entered. This annotation
behavior on function parameter lists is something I'm not terribly pleased
with, but then, the most natural boundary between annotated and unannotated code appears to be that of a function call, so it's possibly sensible to leave extra conveniences there.

It's particularly helpful on return types to avoid forcing control to
flow through a single exit block, in which to write a like expression
in an if whose consequent throws a new TypeError (I got tired just
writing that ;-).

But it helps also on arguments:

function f(a like T, b like U, c like V) {
   ...
}

instead of

function f(a, b, c) {
   if (!(a like T)) throw new TypeError;
   if (!(b like U)) throw new TypeError;
   if (!(c like V)) throw new TypeError;
   ...
}
# Jeff Dyer (16 years ago)

On 5/26/08 11:06 AM, Mark S. Miller wrote:

  • What's "proto" doing in the grammar? If we want to provide access to the internal [[Prototype]] property (as I think we do), we should do that explicitly with a reflective operation such as Object.prototypeOf(obj). But please let's avoid turning this internal property into a named property. Doing so breaks the subset relationship between JSON and EcmaScript. (Granted, we also need to acknowledge that this relationship is currently broken by Firefox. But part of the purpose of standards is to encourage browser vendors to repair their implementations.)

You'll notice that it is used as a keyword in object literals to allow setting up the [[Prototype]] of an object, and as an attribute to mean what 'prototype' used to mean. We felt 'prototype' was already used too broadly to reserve for this specific purpose.

  • What's ">=="? I've never seen that before.

Residue of an erased construct.

  • What does the "var" attribute mean inside an object literal?

  • Now that we have let-at-the-new-var, i.e., a properly lexically scoped letrec behavior, do we still need the "let" expression and the "let" comprehension? Can we kill these?

  • Why does the grammar allow function calls in LeftHandSideExpressions. For example, what's the meaning of

    foo(a)++

?

  • Why does delete operate on a PostFixExpression rather than a LeftHandSideExpression? What's the meaning of

    delete x++;

?

Its a bug, but not the one you are reporting. For compatibility with ES3 the operand of the 'delete' operator must be a /UnaryExpression/. This allows non-sense expressions like 'delete void 0'. The result, in case you are wondering, is /true/.

# Jeff Dyer (16 years ago)

On 5/26/08 12:01 PM, Brendan Eich wrote:

On May 26, 2008, at 11:06 AM, Mark S. Miller wrote:

Doing so breaks the subset relationship between JSON and EcmaScript. (Granted, we also need to acknowledge that this relationship is currently broken by Firefox.

Not Firefox -- both Mozilla JS implementations (SpiderMonkey and Rhino) support proto (readably -- let's ignore the writable case).

ActionScript also had read-only proto in at least one of its versions. I'm not sure if it still does in AS3.

proto is not supported in AS3, to my knowledge. Any anyways, if there is controversy here it should be that proto is being reserved in ES4 and is not as generally usable as in ES3 and ancestors. Not, that it has special meaning at certain points in the grammar.

# Brendan Eich (16 years ago)

On May 26, 2008, at 2:16 PM, Jeff Dyer wrote:

On 5/26/08 12:01 PM, Brendan Eich wrote:

ActionScript also had read-only proto in at least one of its versions. I'm not sure if it still does in AS3.

proto is not supported in AS3, to my knowledge.

I was thinking of

livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html wwhelp.htm?context=LiveDocs_Parts&file=00002585.html

So, ActionScript 2 -- right?

Any anyways, if there is controversy here it should be that proto is being reserved in
ES4 and is not as generally usable as in ES3 and ancestors.

(No proto in ES3, of course.)

Not, that it has special meaning at certain points in the grammar.

Mark's point about JSON, Doug has raised it too, is that magic
property names in an ES standard, if not in a few implementations of
ES3, pre-empt those names from being used as JSON property names.
Even if the identifier proto were not in the grammar -- if it
were only the name of a magic Object.prototype getter -- it would
break the JSON < ES4 relation. But I think that relation is already
broken, since (AFAIK) JSON is not a subset of ES3.

# Jeff Dyer (16 years ago)

On 5/26/08 2:55 PM, Brendan Eich wrote:

On May 26, 2008, at 2:16 PM, Jeff Dyer wrote:

On 5/26/08 12:01 PM, Brendan Eich wrote:

ActionScript also had read-only proto in at least one of its versions. I'm not sure if it still does in AS3.

proto is not supported in AS3, to my knowledge.

I was thinking of

livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html wwhelp.htm?context=LiveDocs_Parts&file=00002585.html

So, ActionScript 2 -- right?

Yes, that's AS2 only.

Any anyways, if there is controversy here it should be that proto is being reserved in ES4 and is not as generally usable as in ES3 and ancestors.

(No proto in ES3, of course.)

Right, which means it can be used as an ordinary identifier.

Not, that it has special meaning at certain points in the grammar.

Mark's point about JSON, Doug has raised it too, is that magic property names in an ES standard, if not in a few implementations of ES3, pre-empt those names from being used as JSON property names. Even if the identifier proto were not in the grammar -- if it were only the name of a magic Object.prototype getter -- it would break the JSON < ES4 relation. But I think that relation is already broken, since (AFAIK) JSON is not a subset of ES3.

Understood. And just to beat this horse to make sure it's really dead, 'proto's appearance in the grammar doesn't make it a special property name -- it just limits where in the language that special property can be referenced.

# Mark S. Miller (16 years ago)

On Mon, May 26, 2008 at 12:01 PM, Brendan Eich <brendan at mozilla.org> wrote:

If I recall correctly (and I'm sure someone will set me straight otherwise), JSON is not compatible with ES3 -- Unicode non-BMP character handling differs. Trying to force a subset relation from JSON to ES4 is not going to fly if JSON is not a subset of ES3.

That's the first I've heard of that problem. AFAIK, JSON, ES3, ES3.1, and ES4 all accept \u surrogate pairs representing a UTF-16 encoding of non-BMP characters. Can anyone say more about what the remaining problem is here?

The only breakage in the subset relationship that I'm aware of are

  • the ES3 stripping of Cf characters, which everyone agrees needs to be fixed in ES3.1 and ES4,

  • and the treatment of \u2028 and \u2029 are newline characters rather than merely whitespace characters. We're fixing this in ES3.1 and proposing that ES4 fix this as well.

Are there other problems?

# Mark S. Miller (16 years ago)

On Mon, May 26, 2008 at 4:57 PM, Jeff Dyer <jodyer at adobe.com> wrote:

But I think that relation is already broken, since (AFAIK) JSON is not a subset of ES3.

Understood. And just to beat this horse to make sure it's really dead,

Last I saw that horse, it merely had a minor injury that was healing rapidly ;).

# Maciej Stachowiak (16 years ago)

On May 26, 2008, at 11:58 AM, Jason Orendorff wrote:

I can answer two more :)

On Mon, May 26, 2008 at 1:06 PM, Mark S. Miller <erights at google.com>
wrote:

  • What does the "var" attribute mean inside an object literal?

See Lars's "ES4 stable draft: Object initializers": mail.mozilla.org/pipermail/es4-discuss/2008-April/002668.html

  • Why does the grammar allow function calls in LeftHandSideExpressions. For example, what's the meaning of

    foo(a)++

?

As far as I know, this is unchanged from ES3, in which "functions are permitted to return References" but "This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference.": bclary.com/2004/11/07/#a-8.7 and an implementation that doesn't hold with such nonsense is also allowed to reject "foo(a)++" as a syntax error: bclary.com/2004/11/07/#a-16

In practice, for Web compatibility, it has to be a runtime error not a
parse error. I don't know of any implementation making use of a
function returning a reference however (in WebKit's implementation
Reference is not a real type, just a spec fiction, and I assume this
is true in other implementations).

# Brendan Eich (16 years ago)

On May 26, 2008, at 11:40 PM, Maciej Stachowiak wrote:

On May 26, 2008, at 11:58 AM, Jason Orendorff wrote:

As far as I know, this is unchanged from ES3, in which "functions are permitted to return References" but "This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference.": bclary.com/2004/11/07/#a-8.7 and an implementation that doesn't hold with such nonsense is also allowed to reject "foo(a)++" as a syntax error: bclary.com/2004/11/07/#a-16

In practice, for Web compatibility, it has to be a runtime error not a parse error.

Could you provide a list of URLs? We added support for "lvalue
return" to SpiderMonkey years ago, based on someone using the code
and wanting to port VBScript-infected JScript. I don't recall the
name (it wasn't AOL :-P), but there may be a post from me in reply on
the old "jseng" Mozilla USENET group.

I don't know of any implementation making use of a function returning a reference however (in WebKit's implementation Reference is not a real type, just a spec fiction, and I assume this is true in other implementations).

SpiderMonkey erases References except where a native function calls a
special API to return one.

# Brendan Eich (16 years ago)

On May 26, 2008, at 5:57 PM, Mark S. Miller wrote:

On Mon, May 26, 2008 at 12:01 PM, Brendan Eich
<brendan at mozilla.org> wrote:

If I recall correctly (and I'm sure someone will set me straight
otherwise), JSON is not compatible with ES3 -- Unicode non-BMP character handling differs. Trying to force a subset relation from JSON to ES4 is not
going to fly if JSON is not a subset of ES3.

That's the first I've heard of that problem. AFAIK, JSON, ES3, ES3.1, and ES4 all accept \u surrogate pairs representing a UTF-16 encoding of non-BMP characters. Can anyone say more about what the remaining problem is here?

Sorry, I was misremembering the problem discussed at

doku.php? id=proposals:update_unicode&s=incompatible+json

which would make JSON not a subset of ES4.

The only breakage in the subset relationship that I'm aware of are

  • the ES3 stripping of Cf characters, which everyone agrees needs to be fixed in ES3.1 and ES4,

Even Microsoft? [1]

  • and the treatment of \u2028 and \u2029 are newline characters rather than merely whitespace characters. We're fixing this in ES3.1 and proposing that ES4 fix this as well.

That's all fine, or to be debated [2]. But the fact remains: JSON is
not a subset of ES3 for these reasons. Let's not bend "subset" via
future tense.

Are there other problems?

These two are enough.

Why is it important that JSON is a subset of ES-future-anything?

/be

[1] bugzilla.mozilla.org/show_bug.cgi?id=368516#c34 [2] doku.php? id=spec:line_terminator_normalization

# Maciej Stachowiak (16 years ago)

On May 26, 2008, at 11:48 PM, Brendan Eich wrote:

On May 26, 2008, at 11:40 PM, Maciej Stachowiak wrote:

On May 26, 2008, at 11:58 AM, Jason Orendorff wrote:

As far as I know, this is unchanged from ES3, in which "functions
are permitted to return References" but "This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference.": bclary.com/2004/11/07/#a-8.7 and an implementation that doesn't hold with such nonsense is also allowed to reject "foo(a)++" as a syntax error: bclary.com/2004/11/07/#a-16

In practice, for Web compatibility, it has to be a runtime error
not a parse error.

Could you provide a list of URLs?

I don't mean that actually supporting Reference return is
incompatible. Just that treating foo(a)++ as a syntax error is
incompatible. In JavaScriptCore we detect at parse time when the
operand of a ++ or -- is not syntactically an lvalue and emit code to
throw an exception at runtime, because apparently some scripts on the
Web include functions with such constructs that they never call, so
treating it as a syntax error and aborting parsing would break the
page, but throwing at runtime does not.

We tried to treat this a syntax error and at the time it broke
300themovie.warnerbros.com and fedex.com. There were probably more
than these two, we did not do an exhaustive search. Since Mozilla and
IE both support this syntax I imagine this is no surprise.

We added support for "lvalue return" to SpiderMonkey years ago,
based on someone using the code and wanting to port VBScript- infected JScript. I don't recall the name (it wasn't AOL :-P), but
there may be a post from me in reply on the old "jseng" Mozilla
USENET group.

I don't know of any implementation making use of a function returning a reference however (in WebKit's implementation Reference is not a real type, just a spec fiction, and I assume this is true in other implementations).

SpiderMonkey erases References except where a native function calls
a special API to return one.

I did not know that. Probably not something we are keen to add.

# Lars Hansen (16 years ago)

-----Original Message----- From: es3.x-discuss-bounces at mozilla.org [mailto:es3.x-discuss-bounces at mozilla.org] On Behalf Of Mark S. Miller Sent: 26. mai 2008 11:07 To: es4-discuss at mozilla.org; es3.x-discuss at mozilla.org x-discuss Subject: A random collection of ES4 draft spec surprises and thoughts

In going over the ES4 draft spec docs, I found the following things surprising:

Other people took care of everything except this one:

  • Is "A catch-all method operates on the object that contains the method." a mistake? Did you mean "operates on the invoked object"?

My phrasing is clumsy, but in my universe we invoke functions and methods, not objects, and I was trying to convey that sense of reality. The sentence does not end with a period but with a second clause: ", not on that object's prototype object." and that's the main point: the method only operates on the specific receiver object, not on the receiver's prototypes. But you're right to point out that it could be improved. Thanks.