tc39 / proposal-class-fields

Orthogonally-informed combination of public and private fields proposals
https://arai-a.github.io/ecma262-compare/?pr=1668
1.72k stars 113 forks source link

Why a new LexicalEnvironment Parameter? #306

Open mgaudet opened 4 years ago

mgaudet commented 4 years ago

I am curious about the design of the specification and its addition of a second lexical environment (PrivateEnvironment) throughout the specification algorithms. By writing this, it feels as if the scope (LexicalEnvironment) and privateScope (PrivateEnvironment) may possibly diverge. I am however unable to see if that’s 1) intended, potentially to support extensions of this proposal 2) possible in the proposal as it exists today.

When first reading about PrivateEnvironment, I had thought that what was going to happen in the specification would be that functions defined in classes would get an additional FunctionLexical environment; this would (I think!) allow the spec to largely operate as is, without having to parallel manipulate private scopes.

Probably missing something, but it did seem a bit odd going through this, so I thought I’d ask.

littledan commented 4 years ago

I'd be open to editorial PRs to change how scoping works, to make it clear that these never diverge, and ensure that future specification changes don't mess it up. However, I'm not sure what you mean exactly. How would you look up a private name in this model?

jorendorff commented 4 years ago

MakePrivateReference would look it up on the environment chain. This isn't much different from how it works in the current proposal. But instead of using ResolveBinding, there would be a similar algorithm, ResolvePrivateName.

(The use of ResolveBinding for private names struck me as really confusing—private names aren't bindings. So if nothing else, maybe consider renaming that algorithm to something generic that works for both concepts!)

jorendorff commented 4 years ago

One thing that I think is clearer if it's done this way is the parallel between the two-level scoping in

(function name1(a = EXPR1) { var name2; EXPR2; })

and in

(class name1 extends EXPR1 { #name2 = EXPR2; })

In both cases, I think there's some undocumented rationale that things defined in braces are only visible in braces, but the name of a FunctionExpression or ClassExpression is scoped to the whole thing, including code just outside the braces.

littledan commented 4 years ago

@jorendorff I'm still having trouble understanding what you're getting at concretely, and how the ResolvePrivateName algorithm would work. One possibility: there could be a new method on all lexical environments, GetPrivateName, in parallel to GetBindingValue, with function environment records storing a separate structure off to the side for private names. Is this along the lines of what you're suggesting?

jorendorff commented 4 years ago

Yes, that's it exactly.

jorendorff commented 4 years ago

I just realized what's bugging me here really isn't specific to this proposal. Rather, the table of function internal slots in the spec seems out of hand already.

A closure is a (code, environment) pair, they say. It would help just to divide these slots into code (FormalParameters, ECMAScriptCode, ConstructorKind, ThisMode, Strict, SourceText, IsClassConstructor) and environment (Environment, Realm, HomeObject, and I think ScriptOrModule).

All of the environment stuff could live in environment records. Then there would be less copying it around—which happens all over the place in the current spec, with the consequence that no important property of these fields is local.

littledan commented 4 years ago

It bothered me in writing this out that an extra thing had to be passed in parallel. It didn't seem very scalable. I like your suggestion.

At the same time, I'm not sure when will be the best time to do this spec refactoring--my coworkers @caiolima and @Ms2ger have worked hard to have PRs against ecma262 for this proposal, but it's been a mess to keep them up to date, and updated with the stack of proposals. I think it'd be easiest if we waited until Stage 4 to make this fixup, so we can avoid repeated work.

jorendorff commented 4 years ago

If what I'm saying here makes sense and is in full agreement with the semantics of the proposal, then I don't mind waiting. I think that's the case—do you agree? (Otherwise I'd like to keep talking and get to clarity.)

littledan commented 4 years ago

Yes, what you're saying is in agreement with the semantics of the proposal; it'd just be an editorial change. Let's do this when merging into the main spec, since it seems like folks are OK with that.

jorendorff commented 4 years ago

Great. Thanks.