01:03:56  * AtumTquit (Remote host closed the connection)
01:30:23  <ljharb>works well for me too. i'd still also like a keyword to refer to the current class (something far more common than recursion ime) but that could still happen later.
02:36:13  * jwaldenquit (Ping timeout: 252 seconds)
05:23:03  * jmdyckquit (Remote host closed the connection)
05:39:54  * howdoijoined
06:11:17  * floatleftquit (Ping timeout: 256 seconds)
06:12:40  * floatleftjoined
06:57:45  * floatleftquit (Ping timeout: 256 seconds)
06:58:29  * floatleftjoined
07:22:17  <Domenic>Bakkot: why does your version work on a subclass
07:22:33  <Bakkot>'cause it just uses a closed-over function
07:22:53  <Bakkot>no typechecks in sight
07:23:08  <Domenic>The typechecks occur when you try to do subclass.#privateField = foo inside the method though
07:23:41  <Domenic>But both of our versions don't use the subclass constructor, they always use `new JSDOM()`
07:23:53  <Domenic>So I don't see why typechecks would occur in my version either
07:24:32  <Bakkot>You're right that your version works (see edit), but only because you wrote `JSDOM.#finalize` rather than (as I expect people to write) `this.#finalize`
07:25:11  <Bakkot>(also I'm currently running a 102° fever, so it is very possibly I am just wrong about things)
07:27:57  <Bakkot>(kind of tempted to suggest we ban _only_ `this.#foo` where `#foo` is a static private field. or at least have the babel plugin give a warning for that? do babel plugins give warnings)
07:30:57  <Domenic>Yeah I was kinda thinking that too
07:31:12  <Domenic>It kind of aligns with the idea of this being sugar over lexical declarations
07:31:58  <Domenic>We could say that `#foo` is always a reference to the static private `#foo`. Whereas you need to qualify with `x.#foo` or `this.#foo` for instance private.
07:32:10  <Domenic>And you can't use dot access to touch static private at all?
07:35:01  <Bakkot>Hm. That's a little awkward - it's weird to have only one of the four forms be different: `class A { ix = 0; #iy = 1; static sx = 2; static #sy = 3; m(){ return this.ix + this.#iy + A.sx + #sy } }`
07:35:48  <Domenic>True
07:37:34  <Bakkot>this is a hard thing to reason about abstractly. maybe we pick a semantics and leave it at stage 2 for a while and see what people's experience of it is via Babel?
07:38:38  <Bakkot>if in fact it ends up being rare to write `this.#staticMethod` instead of `className.#staticMethod`, I'm a lot more comfortable going forward with the old semantics (i.e. the one where it breaks on subclasses).
07:39:09  <Domenic>Seems reasonable. I think most people do not in general use `this` inside their static methods
07:39:17  <Domenic>That might be quantifiable today
07:39:52  <ljharb>they'd face the same hazard doing so with public properties
07:40:06  <Bakkot>ljharb, expand?
07:40:08  <ljharb>so i suspect there's already a lot of inertia against using `this` inside static methods
07:40:30  <ljharb>it's only with `class extends` that subclass constructors inherit from the superclass constructor
07:40:46  <ljharb>ie, with `class extends` there's no hazard, but with all pre-ES6 inheritance, there is one
07:40:51  <ljharb>so i doubt it's very common
07:41:20  <Bakkot>oh. it has not been my impression that most people carried over their pre-ES6 habits to ES6 classes, though I could be wrong.
07:41:28  <ljharb>fair
07:41:41  <ljharb>i dunno tho, i think using `this` in a static method is just super weird
07:41:43  <Domenic>I think the assertion is that people didn't bother to create new habits for calling static methods when they moved to ES6 classes
07:41:50  <ljharb>^ yes, that
07:42:32  <ljharb>since dan's suggestion allows for domenic's use case, without imo creating a new hazard, and also leaves open possibilities for future improvements, i think it sounds great
07:43:09  <Bakkot>Definitely creates a new hazard, though it might turn out to be one people rarely trip over.
07:45:19  <Bakkot>ljharb: you've previously suggested that repeating the class name is a bad thing, so I'm a little surprised you find `this` in static methods weird
07:45:22  <ljharb>well, it restores a pre-ES6 hazard
07:45:36  <ljharb>i think repeating the class name is bad, but `this` is invocation-determined, so that'd be worse
07:46:02  <ljharb>repeating the class name is currently the only robust means of referencing the constructor from a static method
07:46:31  <Bakkot>I often _want_ things to be invocation-determined: that's the whole point of dynamic dispatch
07:47:00  <Bakkot>if I am exposing a class and expecting people to extend it, I may well be intending to allow them to overwrite some of the behavior of the class
07:47:31  <Bakkot>it's more common to do this by overwriting non-static methods, sure, but there's nothing in principle different about static methods here.
07:50:58  <ljharb>sure, and if you want that, you'd use `this`
07:51:47  <Bakkot>and then you'd run into the hazard with subclasses and static private.
07:51:57  <Bakkot>hmmmmm
07:52:02  <ljharb>sure. but Domenic's use case was for base class static private
07:52:16  <ljharb>has anyone come up with a noncontrived one for inherited static private?
07:52:27  <Bakkot>right; that use case is met, but I worry that in allowing it by this proposed semantics we introduce a footgun.
07:52:30  <Bakkot>Domenic: you don't have a usecase for static private *fields*, do you?
07:52:31  <ljharb>like where you'd do `this.#foo` in a static method and expect it to do something useful for subclasses?
07:52:51  <Bakkot>yet another possible resolution occurs to me, one I'm maybe actually happy with:
07:53:38  <Bakkot>a.) no static private fields; prefer closing over variables. b.) static private methods, and *only* static private methods, are copied to subclasses at initialization time.
07:53:53  <Bakkot>er, at subclass definition time, rather.
07:54:56  <Bakkot>b.) is similar to my earlier "reinitialize static fields on subclasses" thing, except that it doesn't have the issue of unexpectedly running code twice: private methods, static or otherwise, do not run code during initialization and are not mutable.
07:55:49  <Domenic>Fields I'd just like so I can logically group my code in the class body
07:56:12  <ljharb>Bakkot: and you'd be fine with static publics as-is, and you think everybody would be ok with the difference?
07:56:19  <Domenic>I really don't think subclasses are worth worrying about or building mechanisms to serve, myself.
07:56:48  <Bakkot>ljharb: yeah, pretty much. I actually don't think anyone would notice the difference, except in noticing there are no static private fields.
07:57:34  <ljharb>and it'd not be ok to have static private fields (that throw on subclass.#foo), and then also have static private methods as you indicated?
07:58:37  <Bakkot>um. I guess I'd be ok with that too, but then people would definitely notice the difference: it would be weird if `static #m(){ return 0; }` didn't throw, but `static #m = () => 0` did.
07:58:43  <ljharb>yeah true
07:59:02  <ljharb>arrow functions in fields is gross tho imo :-/ the airbnb config will be forbidding that one for sure
07:59:11  <ljharb>but yeah that would be a weird inconsistency
07:59:20  <Bakkot>Domenic: I do. I use subclasses a fair bit, actually, if I'm using classes at all.
08:03:54  <Domenic>Ok, it'd be good to provide example code, as I have, where your extra mechanisms provide some advantage.
08:06:32  <Bakkot>Sure, I'll try to write something coherent and real-world-ish when I am coherent again. The basic idea is just that it meets your use clase without running into https://github.com/tc39/proposal-class-fields/issues/43#issuecomment-328681487, though.
08:08:26  <Bakkot>(or, well, the equivalent of that but for static methods instead of static fields.)
09:06:11  <not-an-aardvark>Would it be possible to just have `this#foo` be semantically identical to `(current class)#foo` when used in a static method? The special case is unappealing, but it doesn't seem like it would cause any observable problems given that static fields couldn't be overridden by subclasses anyway.
09:19:38  <Bakkot>I'd strongly prefer we not make `this` even more magical.
09:25:02  <not-an-aardvark>On reconsideration, I agree. Thinking through a less magical variant: I think the reason I expect `this#foo` to work in static methods is because my conceptual model for `this#foo` is effectively the same as something like `this.foo`, aside from the fact that `#foo` is inaccessible outside of the class.
09:25:29  <not-an-aardvark>`this.foo` works on subclasses because it does a prototype chain lookup. What would be the effect of doing a prototype chain lookup for private fields as well?
09:28:35  <not-an-aardvark>i.e. the semantics of `this#foo` would be "if any object on the prototype chain of `this` has the `#foo` field declared in this scope, return the value of that field, otherwise throw"
09:30:39  <not-an-aardvark>If I'm not mistaken, this would be equivalent to the current behavior except with static methods and cases where the prototype of an object is modified.
09:35:42  <not-an-aardvark>(By the way, I've read a lot of the discussion on the proposal repo but have probably missed some as well; please feel free to link me to an issue if this has already been discussed somewhere.)
09:38:51  * AtumTjoined
09:44:48  <Bakkot>not-an-aardvark: I can try to find a previous discussion, but the gist of it is that most of the committee feels strongly that private fields ought not walk up the prototype chain. This is particularly true for private instance fields, but we'd ideally want consistent semantics for private statics.
09:45:13  <Bakkot>ljharb: IIRC you use public static fields a lot, or would like to; can I ask how you do or would like to refer to them?
10:55:56  * floatleftquit (Ping timeout: 260 seconds)
11:25:11  * mylesborinsquit (Quit: farewell for now)
11:25:41  * mylesborinsjoined
11:58:48  * floatleftjoined
12:00:57  * not-an-aardvarkquit (Quit: Connection closed for inactivity)
12:03:26  * floatleftquit (Ping timeout: 252 seconds)
13:06:35  * jmdyckjoined
14:59:53  <littledan>"a.) no static private fields; prefer closing over variables. b.) static private methods, and *only* static private methods, are copied to subclasses at initialization time." This alternative seems really reasonable to me. I expanded on it in the explainer
15:00:13  <littledan>see https://github.com/tc39/proposal-static-class-features#install-private-static-methods-on-subclasses-omit-private-static-fields
15:01:23  <littledan>you could justify the copying semantics by saying, this is the same as what private instance methods do--install themselves in everyplace that you would've gotten them through prototype chain access
15:01:38  <littledan>due to the lack of private prototype chain access
15:02:11  <littledan>I don't think my writeup there is the best edited thing; I'd be happy to replace it or link from it anything else you want to write, Bakkot
15:03:48  <littledan>not-an-aardvark: See https://github.com/tc39/proposal-static-class-features#prototype-chain-walk-for-private-fields-and-methods for a summary of why I'm not proposing a private prototype chain walk
15:04:39  <littledan>it'd be great if any of you who are interested would come to a VC meeting to discuss what we should do about static class features. Write me outside of this channel, and I'll send you a link to sign up on a Doodle.
15:16:08  <littledan>Bakkot: Am I right from the above discussion that you're very concerned about the TypeError issue? Do you not find the arguments in https://github.com/tc39/proposal-static-class-features#static-private-access-on-subclasses convincing?
15:18:31  * bradleymeckjoined
15:18:42  <littledan>Domenic: On the other hand, would you be OK with the alternative Bakkot is proposing, of installing private static methods on subclasses and skipping static private fields? I get the ordering issue but it seems sort of like the weakest use case so far.
16:09:47  <ljharb>Bakkot: right now, i only use the constructor name, and would enforce that via linter if possible - if a keyword like `class.` or `static.` existed, i'd use that insead
16:38:44  <Bakkot>littledan: "Do you not find the arguments in https://github.com/tc39/proposal-static-class-features#static-private-access-on-subclasses convincing?" No. I'll comment in Domenic's thread explaining why.
16:40:16  <Bakkot>ljharb: that's surprising to me in that it doesn't work that well with subclassing: if I have `class Base { static opts = {}; }`, I'd want `class Derived extends Base { static opts = {} }` to use Derived's opts, rather than Base's.
16:46:22  <littledan>Bakkot: Using ad-hoc polymorphism like this seems pretty closely related to something being public, doesn't it?
16:47:07  <littledan>sorry, ad-hoc polymorphism isn't the right word, but still, polymorphism
16:48:24  <Bakkot>commented
17:07:05  * bradleymeckquit (Quit: bradleymeck)
17:08:35  <Bakkot>littledan: Yes, you'd only want (and only get) polymorphism over public fields and methods. but you might want to *use* that polymorphism from private methods, especially if you're using the 'extract method' refactoring the way Domenic describes.
17:11:33  <Bakkot>left a comment explanding on that: https://github.com/tc39/proposal-static-class-features/issues/4#issuecomment-354818186
17:17:32  * bradleymeckjoined
17:28:15  <Domenic>littledan: no, I don't yet see any compelling reason to add machinery for Bakkot's use case, and I also am sad about removing private static fields as I think they're nice for code grouping.
17:29:34  <Domenic>In other words this "you might want polymorphism" case seems extraordinarily hypothetical, especailly for private statics, but even for statics in general.
17:29:51  <Domenic>I don't believe any other language supports that, and I don't think we should be adding machinery to JS or restricting JS features to support it.
17:45:15  * bradleymeckquit (Quit: bradleymeck)
17:53:06  <littledan>I'm not so convinced by the "code grouping" requirement. There's lots of things that we don't allow grouped, e.g., class declarations in the top level of a class (you could do this through static private fields but it would look weird)
17:54:01  <littledan>The reason that supporting private static methods on subclasses isn't all that ad-hoc is that it's actually sort of analogous to instance private methods--it's installed on all the objects that it would've otherwise be found on the prototype chain
18:02:43  * bradleymeckjoined
18:07:32  <Domenic>Classes are all about grouping data and behavior. If you're saying this is a type of data I cannot group, that's frustrating.
18:08:05  <Domenic>Why is that reason not also applicable to static private fields?
18:19:09  * dilijevjoined
18:21:21  <ljharb>Bakkot: it would; `static` there would refer to `Derived`.
18:22:12  <ljharb>Bakkot: the keyword would be nothing more than an immutable way to reference the current lexical `class`
18:28:55  <littledan>Domenic: I really think of classes grouping data and behavior in support of instances; maybe that distinction of "what's in support of instances" is a little unclear, but it seems clear that factory functions like the ones you used in your static private use case does have to do with instances
18:29:18  <Domenic>Sure, and so would any interesting constants that they use
18:29:35  <littledan>yeah, i can see that
18:30:04  <littledan>so, another point on the spectrum is to combine these two things: support static private methods defined on subclasses, while static private fields just on the class
18:30:24  <littledan>again, this would be sort of parallel with what we have for instance private: methods defined on all instances, but fields defined individually on just one of them
18:31:04  <Domenic>If it's parallel, maybe it makes sense, but I didn't realize that we did that bifurcation for private fields
18:31:16  <littledan>well, we had to for private methods, since there's no private prototype chain
18:31:38  <Domenic>I mean, we didn't have to, they could just be actually private, not accessible to subclasses ("protected")
18:31:57  <littledan>I presented private methods in July, you can find the slides here: https://docs.google.com/presentation/d/1hiti-3Upn-v5ez9OCJb3UOXH6ksdFAEWWJyoqe13mAc/edit#slide=id.p
18:32:05  <littledan>they are actually private
18:32:08  <Domenic>Will re-read after this meeting
18:32:30  <littledan>the key decision was whether we should "type check the receiver" of private methods
18:32:41  <littledan>or make the more like lexically scoped functions with funny syntax
18:32:45  <littledan>we decided on type checking
18:33:18  <littledan>Bug thread: https://github.com/tc39/proposal-private-methods/issues/1
18:34:22  <littledan>OK, have a good meeting, talk to you later
19:19:21  * howdoiquit (Quit: Connection closed for inactivity)
19:20:21  <Domenic>littledan: so the slides don't explain why (apparently) private methods get copied to subclasses
19:28:16  * floatleftjoined
20:46:38  <annevk>That’s incompatible with platform objects, right?
20:47:33  <annevk>In that a userland subclass does not have access to any private state
20:54:02  <Domenic>Yeah I don't really understand; does this mean that if we tried to self-host platform objects, we couldn't use private methods, because they'd get copied on to any user-defined subclasses?
21:04:08  <ljharb>ooh, interesting point
21:04:35  <ljharb>actually yeah, if `class extends` means i can runtime-determine the existence of a static private method on a given `class`, then that breaks hard-privacy.
21:04:49  <ljharb>Bakkot ^ thoughts?
21:07:38  <Domenic>I think I'm just not understanding; people say private is really private but then supposedly subclasses also have access which sounds more like protected.
21:18:13  * floatleftquit (Ping timeout: 255 seconds)
21:20:13  <ljharb>it seems like if private static methods are copied, then i could write something like `function hasFooPrivate(TargetClass) { class Sub extends TargetClass { static foo() { return this.#foo(); } } try { Sub.foo(); return true; } catch { return false; } }` without `TargetClass` explicitly exposing that it has a "#foo() {}". if so, that breaks hard privacy, so it's a nonstarter - am i missing something?
21:21:04  * floatleftjoined
22:13:30  * bradleymeckquit (Quit: )
22:23:54  * floatleftquit (Read error: Connection reset by peer)
22:24:46  * floatleftjoined
22:29:20  * floatleftquit (Ping timeout: 248 seconds)
22:30:29  * floatleftjoined
22:59:44  <littledan>Domenic: I'm not sure what you mean. They're copied on, but the names aren't accessible in subclasses
22:59:55  <Domenic>Then I don't understand what copied on means.
23:00:16  <littledan>it's just like when a superclass defines a private field: subclass instances have the field, but they can't access it
23:00:29  <ljharb>ahhh right ok
23:00:39  <Domenic>That analogy doesn't help me at all.
23:00:45  <littledan>here, the private method method is callable *by things in the superclass body*, but that's it
23:00:47  <littledan>that's what copying means
23:01:02  <littledan>an object "having a private method" means that calling it, from the scope where the name is visible, doesn't throw a TypeError
23:01:19  <littledan>it doesn't affect the scope where the name is visible (which is still lexical, possibly modulo decorators)
23:01:23  <Domenic>OK, yeah, it's much less confusing to say that the brand check is loosened, than to say that the method is copied there
23:01:40  <littledan>oh, sure, but "brand" is ambiguous, that's why I've been avoiding that terminology
23:01:58  <littledan>but, yes, you could say each private method has a "brand", and subclass instances are branded
23:02:01  <Domenic>Well, replacing it with completely undefined terminology isn't much better ;)
23:02:21  <littledan>heh it's defined in my head--it makes sense if you have the whole private methods spec in mind :)
23:02:36  <Domenic>Branding subclass constructors with their superclass brands seems reasonable from that perspective
23:02:37  <littledan>so, the idea with this alternate proposal is that subclass constructors would also get the static private method "brand"
23:02:49  <littledan>OK!
23:02:57  <Domenic>Does this extend to fields?
23:03:05  <littledan>I don't think so--fields are mutable
23:03:15  <littledan>so we can't just "extend a brand", we have to say what the value is
23:03:18  <Domenic>They are also mutable for instance
23:03:36  <littledan>yes, but we don't have this issue of several things having the same brand
23:03:47  <Domenic>What several things?
23:04:00  <littledan>in spec mechanics, think of it like a desugaring that we give an internal slot to the objects with the private field or private method
23:04:12  <littledan>for private fields, the value of the internal slot is the value of the field, and it's mutable
23:04:22  <littledan>for private methods, it's just a sentinel
23:04:35  <Domenic>Why?
23:04:35  <littledan>we can give as many things as we want the private method brand because there's nothing to it
23:05:04  <Domenic>Why not use the method model for fields too?
23:05:16  <littledan>I'm not sure what that would mean; where would you store the value?
23:05:31  <Domenic>In a separate internal slot I guess, but access to it is guarded by the sentinel?
23:05:35  <littledan>ultimately, for static public fields, you have this property where a Set creates a new own property
23:05:41  <littledan>and a Get will read up the prototype chain
23:06:00  <Domenic>I'm interested in the private instance <-> private static symmetry at the moment.
23:06:06  <littledan>I'm not sure what we want to do for static private fields--we could do a bunch of work to replicate that, but as bakkot points out, the existing semantics are weird anyway
23:06:07  <Domenic>as well as the method <-> field symmetry
23:06:20  <Domenic>I'm less interested in the public <-> private symmetry at the moment.
23:06:34  <littledan>well ,my idea for being symmetric with private instance fields is to throw a TypeError when accessing a static private field from a subclass
23:06:53  <littledan>another possibility is to have it be like an accessor that gets at the superclass private field
23:07:09  <littledan>or another is to have it be an own private field that's initialized the same way as the superclass private field
23:07:28  <littledan>do you like one of these? or do you have another idea of what the semantics should be?
23:07:29  <Domenic>I think the accessor was where I was heading. But I am confused now what is symmetric with what, hmm...
23:07:49  <Domenic>Trying to formulate a question.
23:08:24  <littledan>I don't really think any of these are really more symmetric than any other. They're just complicated edge case semantics. My intuition is to pick the simplest one (if we include this feature)
23:08:57  <littledan>however, others have intuitions that are different; I'm not sure what others think since most discussion so far has been about methods
23:09:14  <Domenic>I guess I am still confused why we're extending the brand for methods but not for instances. The answer I got was about spec mechanics but that was unsatisfying. The accessor strategy seems more symmetric, if I understand it.
23:09:24  <Domenic>s/instances/fields/
23:09:53  <littledan>the reason is, there's no good semantics for what Get and Set should do on inherited static fields
23:10:13  <littledan>to put it another way
23:10:36  <littledan>both treating it like a new field and the same as the superclass are not parallel to other things
23:11:30  <littledan>you need more than a brand, you need a storage cell. Where should this be?
23:11:58  <Domenic>It seems to me that you're making Call be able to work inside subclasses (by extending the brand), but not extending the same courtesy to Get/Set.
23:12:10  <Domenic>(maybe Invoke instead of Call)
23:12:12  <littledan>no, you can just get a static method
23:12:24  <Domenic>I mean for fields
23:12:25  <littledan>the thing about static methods is they're immutable and always set to the initial value
23:12:51  <littledan>this makes it possible to think about it as a brand rather than an internal slot
23:12:58  <Domenic>I don't think this immutable vs. mutable thing should impact it. I understand it does at some spec mechanics level but from a programmer experience perspective it seems irrelevant.
23:13:11  <littledan>I'm not sure what you want the semantics to be
23:13:23  <Domenic>Time for example code, I think
23:13:29  <littledan>I think any particular choice of semantics will have an imperfect programmer experience
23:14:01  <littledan>it's hard for me to think of examples where you really want to take advantage of mutable static private fields...
23:14:14  <littledan>all the static private field examples I was thinking of are immutable
23:14:33  <littledan>the mutable examples feel like bad design that I wouldn't want to advocate for
23:15:12  <Domenic>https://www.irccloud.com/pastebin/Z1QxhG2o/private-static.js
23:15:34  <littledan>To expose the issue, you'd need to write to the static private field
23:15:36  <Domenic>From what I understand, with the design you're proposing where we extend the brand but only for methods, x will succeed but y will fail
23:15:47  <littledan>yes
23:15:54  <Domenic>OK. That bugs me.
23:16:05  <littledan>OK, what do you want to happen when you write to the static private field?
23:16:17  <Domenic>I see.
23:16:27  <littledan>Bakkot's original solution, of re-running the static field initializers in subclasses, is one way to solve it, but I don't like it for other reasons
23:16:48  <littledan>I don't like re-running the static field initializers because it makes subclassing into a factory for stateful objects, which just doesn't seem all that natural
23:16:58  <Domenic>So for public static it'd modify A.publicProp I guess
23:18:16  <Domenic>Extending that to private static feels a bit bad but I'm not sure why?
23:18:21  <littledan>for public static, if you do B.publicProp++, A.publicPro would be 5 and B.publicProp would be 6
23:18:27  <Domenic>Wait it would
23:18:33  <littledan>err I should check
23:18:33  <Domenic>Whaaaaa
23:18:45  <Domenic>That seems like it'd require running the initializers twice
23:19:38  <littledan>no, this is just how Set on prototype chains works
23:20:07  <littledan>let x = { a: 1 }; let y = { __proto__: x }; y.a++; then x.a is 1 and y.a is 2
23:20:47  <littledan>so, this was a core argument of Bakkot's for why we should do Something Different for public static fields, to shield programmers from this source of craziness
23:21:51  <Domenic>Well, I appreciate you catching me up; it's increasingly clear this is well-trodden ground
23:22:30  <littledan>well, I think much of the committee is where you're coming from; this is probably good to include in a presentation
23:22:51  <littledan>so this is really helpful for me
23:23:03  <littledan>given all this--do you have an idea of what to do for private static fields?
23:23:30  <littledan>actually replicating the weirdness that is ordinary properties and prototype chains seems out of the question to me
23:24:47  <Domenic>I would like to have them, but it seems like keeping them symmetric on any dimension is not very possible, so something simple seems nice. E.g. lexically-scoped variable sugar, or just the existing proposal with type checks. "Like an accessor" sounds kind of intriguing, maybe with a throwing "setter"?
23:25:45  <littledan>I have a feeling we won't end up doing lexically scoped variable sugar, just since it'd be strange to have this one corner be without any checks when the other three do have checks
23:25:57  <littledan>(we could do this for private methods, but rejected it)
23:26:20  <Domenic>I think the case is stronger for static, but I don't insist, by any means.
23:26:35  <Domenic>i.e. for private static both methods and fields
23:26:38  <littledan>having a getter with a throwing setter is an option, though it's pretty complicated in the specification and implementation
23:27:11  <littledan>(for subclasses, it'd throw; in the base class, it would just set it)
23:27:50  <Domenic>I might present those two options to the committee? "Here's a simple version with a small sharp edge; here's a complicated version that smooths that over. I'm pretty sure nobody's going to hit this sharp edge, but it's an option..."
23:28:00  <ljharb>isn't the hazard not just assignment tho, but mutation?
23:28:02  <Domenic>You could even evolve to the accessor-esque version in the future if people run into the TypeError too much?
23:28:13  <ljharb>iow `this.#somethingStatic.foo++`?
23:28:36  <littledan>ljharb: Well, I'm assuming we're treating that as "not a hazard"
23:28:43  <littledan>this is a case of me disagreeing with Bakkot and sort of putting my foot down
23:28:57  <littledan>I wrote an explanation why in the static class features explainer
23:29:02  <ljharb>i'm fine treating it as not a hazard; i consider it such for public fields too (because it's so historic and well-known)
23:29:23  <littledan>yep, it's definitely there for public fields to the same extent as private fields
23:30:03  <littledan>Domenic: That's a reasonable phrasing--we'll start with throwing on reads and writes, knowing that this is "fixable" with the getter-in-subclasses semantic change
23:30:58  <littledan>With a mess of decorators you could implement the getter in subclasses, but I don't know if that's worth considering...
23:32:45  <littledan>Domenic: After the last meeting, where I presented various options to the committee and it led to some kind of indecision, I'm thinking to start with a particular preferred option, along with some other backpocket alternatives to switch to, rather than leaving the discussion totally open
23:32:55  <Domenic>+1
23:33:10  <Domenic>Spend some time honing the arguments
23:33:32  <littledan>yeah
23:33:44  <Domenic>Ideally you want it to go like my yield -> yield await presentation did, where by the end everyone was like "yes, you convinced us, we agree, no questions"
23:36:45  <littledan>yes, that would be great
23:39:16  * not-an-aardvarkjoined
23:43:18  <littledan>does anyone else here have any thoughts on these issues?
23:43:37  <littledan>BTW you can't use private fields for another reason: they won't work cross-realm
23:50:04  <Domenic>All the cross-realm cases would be "friend" cases anyway, which will need decorators, which could probably make them work cross-realm
23:53:55  <Bakkot>Domenic: fwiw the polymorphism use case isn't hypothetical; I expecting subclasses to overwrite
23:53:59  <Bakkot>er
23:54:10  <Bakkot>*I have written code expecting subclasses to overwrite static methods
23:54:29  <Domenic>Private ones, though?
23:54:59  <Bakkot>I'm not ever expecting subclasses to overwrite private methods, of course
23:55:31  <Bakkot>but it seems reasonable that I might want to put some of the code which is expecting overwritten static methods in static private methods
23:55:58  <Bakkot>in the same way you might want to put any other shared code in static private methods
23:56:54  <not-an-aardvark>littledan: thanks for the link earlier, I had forgotten that `[[GetPrototypeOf]]` would be observable on proxies
23:57:32  <littledan>Domenic: The cases here are static private methods, which are not overwritable, calling overwritable public static methods