Subset relation (was: RE: ES3.1 Draft: 11 June 2008 version available)

# Lars Hansen (17 years ago)

Intuitively the "subset relation" is determined by the rule that a processor for version n+d (for d > 0 but not necessarily integer or

indeed rational...) of the language should accept all programs P valid under version n, and P should evaluate to the same results in version n+d, except that P may have to be rewritten if:

1 P uses an identifier that became a keyword in n+d

2 P makes use of a feature that changed behavor in n+d due to a "bug fix"

3 P (or portions of P) is strict, n+d has a stricter strict mode than n, and P runs afoul of a feature that has been firmed up in n+d

4 P introduces a variable or property on a built-in object or type but n+d has introduced a variable or property of the same name

5 P relies on exceptions that are thrown by a version n language processor because portions of P are invalid (typically, syntax errors)

Item 1 is handled by opt-in; a version n+d processor is expected to process a version n program by not recognizing keywords introduced in n+d, but otherwise treat the program as a version n+d program.

Item 2 has been discussed extensively; the rule of thumb for a bug fix is that the change must fix many more programs than it breaks. The canonical example is the handling of regular expression literals, which are evaluated once in ES3 programs but every time they are reached during evaluation in ES4 (and in ES3.1 as far as I could tell from the latest draft), but a long list is given on the wiki: proposals:bug_fixes. (Some of those are still too big to be simple bug fixes, and some are no longer approved for inclusion, but most are still good.)

Item 3 hasn't been discussed much, but during the last meeting Brendan, Mark, and I did talk about it and agreed that it would be OK for strict modes to become stricter as the language version goes up. The example in question was the way ES3.1 wants to deal with number-of-arguments checking in strict mode: it wants to allow a mismatching number of arguments in strict mode only if the arguments object is mentioned explicitly in the program text. That is a hack not required for ES4, which has syntax for optional parameters and explicit rest parameters, and which will want to disallow a mismatching number of arguments in strict mode in all cases (in other words, there will be limited uses for the arguments object in ES4 strict mode).

Items 4 and 5 are sanctioned by the ES3 spec (Chapter 16). In ES4, all new global names are in the ES4 namespace in order to reduce the risk associated with introducing new global names.

The issue that was raised by the discussion quoted below was whether strict mode could become /looser/ as the language version goes up; could ES3.1 outlaw 'with' in strict mode, but ES4 allow it again? This feels weird to me.

# Douglas Crockford (17 years ago)

The issue that was raised by the discussion quoted below was whether strict mode could become /looser/ as the language version goes up; could ES3.1 outlaw 'with' in strict mode, but ES4 allow it again? This feels weird to me.

The thing that needs to be maintained is the viability of programs that are written without anticipation of the characteristics of future standards. I don't think that needs to include the strict interpretation of what the strict mode disallows. For ES3.1, strict mode indicates that the programmer wants to use a more reliable subset of the language. If ES4's objectives are different, I think it can have its own definition of strict mode.

I agree that it is weird that ES4 wants to retain with, but that in itself does not disturb the superset relationship.

# Mark S. Miller (17 years ago)

On Mon, Jun 16, 2008 at 2:07 PM, Douglas Crockford <douglas at crockford.com> wrote:

I agree that it is weird that ES4 wants to retain with, but that in itself does not disturb the superset relationship.

Before we retreat into less formal notions of subsetting, could someone please explain why ES4 wants to retain "with" in ES4 strict mode?

# Mark S. Miller (17 years ago)

On Mon, Jun 16, 2008 at 2:45 PM, Mark S. Miller <erights at google.com> wrote:

On Mon, Jun 16, 2008 at 2:07 PM, Douglas Crockford <douglas at crockford.com> wrote:

I agree that it is weird that ES4 wants to retain with, but that in itself does not disturb the superset relationship.

Before we retreat into less formal notions of subsetting, could someone please explain why ES4 wants to retain "with" in ES4 strict mode?

Given the silence, I thought it might be worth pointing out:

  • "Reformed with" was dropped from ES4 strict because it wasn't enough less horrible than "with" to be worth it. If "reformed with" isn't good enough, does anyone think "with" is somehow better than "reformed with"?

  • Given Brendan's and Maciej's clarifications, it seems that "with" is the only remaining feature of ES4 strict preventing static scope analysis.

If the ES4 folks still wish to include "with" in ES4 strict, perhaps they can clarify what they see as the purpose of strict mode. Because I'm completely baffled.

# Maciej Stachowiak (17 years ago)

On Jun 16, 2008, at 8:09 PM, Mark S. Miller wrote:

On Mon, Jun 16, 2008 at 2:45 PM, Mark S. Miller <erights at google.com>
wrote:

On Mon, Jun 16, 2008 at 2:07 PM, Douglas Crockford <douglas at crockford.com> wrote:

I agree that it is weird that ES4 wants to retain with, but that
in itself does not disturb the superset relationship.

Before we retreat into less formal notions of subsetting, could someone please explain why ES4 wants to retain "with" in ES4 strict mode?

Given the silence, I thought it might be worth pointing out:

  • "Reformed with" was dropped from ES4 strict because it wasn't enough less horrible than "with" to be worth it. If "reformed with" isn't good enough, does anyone think "with" is somehow better than "reformed with"?

  • Given Brendan's and Maciej's clarifications, it seems that "with" is the only remaining feature of ES4 strict preventing static scope analysis.

If the ES4 folks still wish to include "with" in ES4 strict, perhaps they can clarify what they see as the purpose of strict mode. Because I'm completely baffled.

I can't speak for the main ES4 designers, and I don't personally see
why "with" needs to be supported in strict mode. But I imagine the
reasoning goes like this:

  • Strict mode is a "good taste" mode, like Perl's "use strict", not a
    mode designed to give any specific guarantees about analyzability
  • "with" is popular among JavaScript authors today, and even in JS
    libraries, so:
    • it would be hard to declare it beyond the boundaries of good taste
    • it would needlessly inhibit adoption of strict mode to have it

I would personally consider "with" to be in bad taste, notwithstanding
its popularity.

, Maciej

# Brendan Eich (17 years ago)

On Jun 16, 2008, at 8:09 PM, Mark S. Miller wrote:

On Mon, Jun 16, 2008 at 2:45 PM, Mark S. Miller
<erights at google.com> wrote:

On Mon, Jun 16, 2008 at 2:07 PM, Douglas Crockford <douglas at crockford.com> wrote:

I agree that it is weird that ES4 wants to retain with, but that
in itself does not disturb the superset relationship.

Before we retreat into less formal notions of subsetting, could someone please explain why ES4 wants to retain "with" in ES4 strict mode?

Given the silence,

I am not going to repeat what I wrote at an earlier point in this
thread (13 June at 10:24) -- you didn't reply to what I wrote then.
Did that message not reach you?

I thought it might be worth pointing out:

  • "Reformed with" was dropped from ES4 strict because it wasn't enough less horrible than "with" to be worth it.

That's not the reason for dropping it. It was considered sufficient
to migrate existing 'with' into, as well as support novel 'with' uses
under, ES4 strict mode -- without loss of lexical scope. But it was
not cheap (requiring invariant type checking), and it was a special
case that could be cut without affecting the core language. The
degree to which it would be used was open to debate. Again, is the
carrot of strict mode worth the stick of adding type annotations to
'with' heads?

Forbidding 'with' in strict mode raises the "rewrite tax" beyond an
addition to the 'with' head, requiring analysis and rewriting to use
a short-hand let binding to denote the head object. There is no "let
ref" (Modula 3); it's not enough to destructure object properties
into individual same-named let bindings, because mutations won't
update the object's properties.

If "reformed with" isn't good enough, does anyone think "with" is somehow better than "reformed with"?

The question isn't whether an existing statement is "good enough",
it's whether a strict mode that bans it is "usable enough".

  • Given Brendan's and Maciej's clarifications, it seems that "with" is the only remaining feature of ES4 strict preventing static scope analysis.

The global object still allows new names to be usable via lexical
references, where the names were not bound at static analysis
(compile) time.

If the ES4 folks still wish to include "with" in ES4 strict, perhaps they can clarify what they see as the purpose of strict mode. Because I'm completely baffled.

Methinks you protest too much. You are right to point to reformed
with, since it was my idea for making with tolerable to an earlier
notion of 'use strict' -- strict mode as a verifier, which would need
to see name bindings in order to do type checking.

This old notion of strict mode was to be an optional feature, at the
implementation's discretion. We dropped it in favor of 'use strict' a
la Perl -- "use good taste and sanity". Without type checking, the
argument against unreformed 'with' is reduced to one about static
scope -- but the global object still frustrates static scope, so is
kicking 'with' out of strict mode worth it, especially if it impairs
adoption of "use strict"?

# Mark S. Miller (17 years ago)

On Mon, Jun 16, 2008 at 10:19 PM, Brendan Eich <brendan at mozilla.org> wrote:

I am not going to repeat what I wrote at an earlier point in this thread (13 June at 10:24) -- you didn't reply to what I wrote then. Did that message not reach you?

Are you referring to mail.mozilla.org/pipermail/es3.x-discuss/2008-June/000108.html?

It was the closest match I could find. I responded to this message. What remaining point in this message do you feel still needs to be addressed? I'm not being difficult. I just reread this message and couldn't spot it.

If "reformed with" isn't good enough, does anyone think "with" is somehow better than "reformed with"?

The question isn't whether an existing statement is "good enough", it's whether a strict mode that bans it is "usable enough".

A strict mode which doesn't ban is clearly not.

  • Given Brendan's and Maciej's clarifications, it seems that "with" is the only remaining feature of ES4 strict preventing static scope analysis.

The global object still allows new names to be usable via lexical references, where the names were not bound at static analysis (compile) time.

If you get rid of "with", then the static analysis rule in ES4 becomes very simple: all free variables in a program (script, compilation unit, whatever) are global references, to be looked up as properties of that program's global object, whether or not those properties are present.

If the ES4 folks still wish to include "with" in ES4 strict, perhaps they can clarify what they see as the purpose of strict mode. Because I'm completely baffled.

Methinks you protest too much. You are right to point to reformed with, since it was my idea for making with tolerable to an earlier notion of 'use strict' -- strict mode as a verifier, which would need to see name bindings in order to do type checking.

This old notion of strict mode was to be an optional feature, at the implementation's discretion. We dropped it in favor of 'use strict' a la Perl -- "use good taste and sanity".

And is "with" either in good taste or sane?

Without type checking, the argument against unreformed 'with' is reduced to one about static scope -- but the global object still frustrates static scope,

The global object makes the contents of the global scope unknown. But it does not ambiguate which variable name occurences are to be interpreted as references into this global scope. Without "with", ES4 strict scopes would be statically analyzable. I'm surprised you're willing to give that up.

so is kicking 'with' out of strict mode worth it, especially if it impairs adoption of "use strict"?

Yes. Otherwise I don't see the point of "use strict".

# Brendan Eich (17 years ago)

On Jun 16, 2008, at 10:48 PM, Mark S. Miller wrote:

On Mon, Jun 16, 2008 at 10:19 PM, Brendan Eich
<brendan at mozilla.org> wrote:

I am not going to repeat what I wrote at an earlier point in this
thread (13 June at 10:24) -- you didn't reply to what I wrote then. Did that
message not reach you?

Are you referring to <mail.mozilla.org/pipermail/es3.x-discuss/2008-June 000108.html>?

Yes.

It was the closest match I could find. I responded to this message. What remaining point in this message do you feel still needs to be addressed? I'm not being difficult. I just reread this message and couldn't spot it.

You replied only to the bit about reformed with, where I wrote:

"Reformed with" was an attempt to restore lexical scope by exact
type annotation. That's what people voted down, not the ES1-3
"with" statement.

but that was not the main point (since reformed with was withdrawn),
it was just setting the record straight ("reformed with", not "strict
with" -- and the fact that it was voted down with red on the
spreadsheet does not argue against plain old "with" being allowed in
strict mode).

The main point was that (a) 'with' is widespread and popular;
therefore (b) strict mode that bans 'with' could fail to be used.

The question isn't whether an existing statement is "good enough",
it's whether a strict mode that bans it is "usable enough".

A strict mode which doesn't ban is clearly not.

Why "clearly"? Usability depends on users and "ergonomics". Something
about 'with' is usable enough that users persist in writing programs
using it. These users say (when they speak up coherently at all) that
'with' makes the language more convenient. Well-known JS hackers say
this, to me even, and get annoyed by nagging such as was found in
older Firefoxes (console warnings about "deprecated with").

If you get rid of "with", then the static analysis rule in ES4 becomes very simple: all free variables in a program (script, compilation unit, whatever) are global references, to be looked up as properties of that program's global object, whether or not those properties are present.

That allows lexical-reference typos through to run-time, where they
become errors -- that is not something the old, withdrawn strict mode
in ES4 allowed.

It's true that 'with' prevents analysis from deciding where a free
name will be found, but with the old strict mode, that's actually a
useful escape hatch. Otherwise (no 'with') the name would have to
resolve to a compiler-visible global definition, or you would have to
reach for eval.

This old notion of strict mode was to be an optional feature, at the implementation's discretion. We dropped it in favor of 'use
strict' a la Perl -- "use good taste and sanity".

And is "with" either in good taste or sane?

I avoid 'with', but I try not to confuse my taste with others' tastes
(plural), or with necessity. Why is it necessary for strict mode to
ban 'with'?

The global object makes the contents of the global scope unknown. But it does not ambiguate which variable name occurences are to be interpreted as references into this global scope. Without "with", ES4 strict scopes would be statically analyzable. I'm surprised you're willing to give that up.

As I wrote previously, all browser implementations have to support
'with' and deoptimize code in its body. There's no savings to be had
in rejecting it from strict mode, and doing so takes a tiny bit of
extra code. On the other hand, such a strict mode may be less used
than 'with', because of 'with' perduring.

Is 'with' any worse than eval, for the purposes of the analysis you
have in mind, if you already allow the "operator" form of eval in
strict mode?

so is kicking 'with' out of strict mode worth it, especially if it impairs adoption of "use
strict"?

Yes. Otherwise I don't see the point of "use strict".

Can you define the point of "use strict" other than by appealing to
taste?

# Pratap Lakshman (VJ#SDK) (17 years ago)

Since we are discussing 'with' in particular - it may be difficult to tighten spec language to fix 'with', but I do believe that if there is some way in which we can deprecate/ban 'with' we should consider it.

For e.g. 'with' interacts with other language features in surprising ways. Consider the following (contrived) case:

var a = 1; function foo() { var o = {a : 2};

with (o) {
    var a = 3;
}

print (a);
print(o.a);

} foo(); print(a);

While it would look like the variable declaration from within 'with' should create a variable at foo scope and set its value to 3, that's not what's supposed to happen. Rules for variable instantiation (§10.1.3), variable declaration grammar (§12.2), identifier reference (§11.1.2), and scope chain and identifier resolution (§10.1.4) result in the above code being evaluated as if it were the following:

var a = 1; function foo() { var o = {a : 2}; var a = undefined;

with (o) {
    a = 3;
}

print(a);
print(o.a);

} foo(); print(a);

Notice that "var a = 3" ends up creating the variable in one scope and setting the value on an element in another scope. How can that be intentional? It may be difficult to tighten spec language to fix this, but we should consider deprecating/banning 'with' in an opt-in 'strict' mode (or 'subset' mode).

pratap

From: es4-discuss-bounces at mozilla.org [mailto:es4-discuss-bounces at mozilla.org] On Behalf Of Brendan Eich Sent: Tuesday, June 17, 2008 12:20 PM To: Mark S. Miller Cc: es3.x-discuss at mozilla.org; es4-discuss at mozilla.org; Douglas Crockford Subject: Re: Subset relation (was: RE: ES3.1 Draft: 11 June 2008 version available)

On Jun 16, 2008, at 10:48 PM, Mark S. Miller wrote:

On Mon, Jun 16, 2008 at 10:19 PM, Brendan Eich <brendan at mozilla.org<mailto:brendan at mozilla.org>> wrote:

I am not going to repeat what I wrote at an earlier point in this thread (13 June at 10:24) -- you didn't reply to what I wrote then. Did that message not reach you?

Are you referring to mail.mozilla.org/pipermail/es3.x-discuss/2008-June/000108.html?

Yes.

It was the closest match I could find. I responded to this message. What remaining point in this message do you feel still needs to be addressed? I'm not being difficult. I just reread this message and couldn't spot it.

You repliedmail.mozilla.org/pipermail/es3.x-discuss/2008-June/000109.html only to the bit about reformed with, where I wrote:

"Reformed with" was an attempt to restore lexical scope by exact type annotation. That's what people voted down, not the ES1-3 "with" statement.

but that was not the main point (since reformed with was withdrawn), it was just setting the record straight ("reformed with", not "strict with" -- and the fact that it was voted down with red on the spreadsheet does not argue against plain old "with" being allowed in strict mode).

The main point was that (a) 'with' is widespread and popular; therefore (b) strict mode that bans 'with' could fail to be used.

The question isn't whether an existing statement is "good enough", it's whether a strict mode that bans it is "usable enough".

A strict mode which doesn't ban is clearly not.

Why "clearly"? Usability depends on users and "ergonomics". Something about 'with' is usable enough that users persist in writing programs using it. These users say (when they speak up coherently at all) that 'with' makes the language more convenient. Well-known JS hackers say this, to me even, and get annoyed by nagging such as was found in older Firefoxes (console warnings about "deprecated with").

If you get rid of "with", then the static analysis rule in ES4 becomes very simple: all free variables in a program (script, compilation unit, whatever) are global references, to be looked up as properties of that program's global object, whether or not those properties are present.

That allows lexical-reference typos through to run-time, where they become errors -- that is not something the old, withdrawn strict mode in ES4 allowed.

It's true that 'with' prevents analysis from deciding where a free name will be found, but with the old strict mode, that's actually a useful escape hatch. Otherwise (no 'with') the name would have to resolve to a compiler-visible global definition, or you would have to reach for eval.

This old notion of strict mode was to be an optional feature, at the implementation's discretion. We dropped it in favor of 'use strict' a la Perl -- "use good taste and sanity".

And is "with" either in good taste or sane?

I avoid 'with', but I try not to confuse my taste with others' tastes (plural), or with necessity. Why is it necessary for strict mode to ban 'with'?

The global object makes the contents of the global scope unknown. But it does not ambiguate which variable name occurences are to be interpreted as references into this global scope. Without "with", ES4 strict scopes would be statically analyzable. I'm surprised you're willing to give that up.

As I wrote previously, all browser implementations have to support 'with' and deoptimize code in its body. There's no savings to be had in rejecting it from strict mode, and doing so takes a tiny bit of extra code. On the other hand, such a strict mode may be less used than 'with', because of 'with' perduring.

Is 'with' any worse than eval, for the purposes of the analysis you have in mind, if you already allow the "operator" form of eval in strict mode?

so is kicking 'with' out of strict mode worth it, especially if it impairs adoption of "use strict"?

Yes. Otherwise I don't see the point of "use strict".

Can you define the point of "use strict" other than by appealing to taste?