Repository navigation
Design Meeting Notes, 6/9/2017 #16415
Copy link
Copy link
Closed
Labels
Design NotesNotes from our design meetingsNotes from our design meetings
Description
Stricter generic signature checks
- Already did some work in Infer from generic function return types #16072 to perfom type argument inference using the return type of a signature as a target.
- In Contextual generic function types #16305 we added support for signatures to gain type parameters from their contextual types.
- This behavior is more appropriate because it respects the constraints and the universality of each usage of type parameters.
- To follow up with this, we're introducing stricter generic signature checks (Stricter generic signature checks #16368).
- Previously, when relating type parameters, we would erase them with the type
any. - This was fairly unsafe.
- Previously the following would work, but with Stricter generic signature checks #16368, the following is an error.
type A = <T, U>(x: T, y: U) => [T, U]; type B = <S>(x: S, y: S) => [S, S]; function f(a: A, b: B) { a = b; // Error b = a; // Ok }
- This is kind of a form of unification between the two parameters.
- We infer using the type parameters of the target, as if we were calling the source with the target's parameters.
- In other words, in
a = babove, it simulates callingbwitha's parameters.
- In other words, in
- We infer using the type parameters of the target, as if we were calling the source with the target's parameters.
- The caveat is that this logic is only applied to single-signature types.
- Any times you have overloads, it becomes extremely difficult to perform these checks.
- Previously, when relating type parameters, we would erase them with the type
- So the question is: do we put this behind a flag?
- Most errors are good, but it's hard to figure out what to do for some advanced scenarios.
- Get it into
masterand see what we can work with.
Private Slots
Proposal: https://github.com/tc39/proposal-private-fields/ (Permalink)
Repo: https://tc39.github.io/proposal-private-fields/
-
How does this work with existing modifiers?
-
Can we offer a true downlevel translation?
- To ES5?
- No.
- Need weakmaps
- Yes above ES6.
- To ES5?
-
Could give a mangled name in ES5/ES3.
- Has potential problems.
- Proxies, enumeration, etc.
- Proxies and the like don't exist in ES5.
- Best effort might be fine.
- Proxies, enumeration, etc.
- Has potential problems.
-
What about using Symbols in ES6?
- Symbols aren't truly private - can be used by proxies, can be iterated over, etc.
-
Weakmaps make it truly private.
- Are they performant?
- Concerns over the type of GC pressure it may cause.
- Edge is good at this!
- Implementation is that every object has a list of weakmaps so that the lookup is inverted.
- Others not as much at this point in time.
- But will eventually improve!
- But it's all opt-in.
- Is it possible that all users really want is design-time private?
- There are definitely people who've wanted private state.
- Are they performant?
-
P.S.
everyone hates the syntax.we're not big on the syntax -
Completely unrelated
- The proposal breaks JScript 5.8 in IE 8.
- ¯\_(ツ)_/¯
- The proposal breaks JScript 5.8 in IE 8.
-
We'll all need to go over the FAQ more closely on the private state proposal repo.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Design NotesNotes from our design meetingsNotes from our design meetings
Activity
kitsonk commentedon Jun 13, 2017
Just a comment with the ES5 down-emit with private members, if you considered the async/await down emit pattern by assuming
WeakMapit would be nice to have the down-emit and have those of us stuck in ES5 provide the polyfill.kitsonk commentedon Jun 13, 2017
Also from a Dojo (@dojo) perspective we have debated a lot of putting private state in weak maps. We just know that if it is accessible, people will abuse it and the only way to to ensure it to promote it being truly private. The biggest challenge is that we have in some cases run into having to name privates in descendent classes silly things because of private member name conflicts, which makes code unclear.
kitsonk commentedon Jun 13, 2017
And P.S. I hate the syntax for the record too... 😂
littledan commentedon Jun 20, 2017
Hey, thanks for the feedback about the syntax. The rationale is documented in the FAQ. Does anyone have any other suggestions?
What's the concern here?
styfle commentedon Jun 20, 2017
Daniel Ehrenberg (@littledan) The FAQ doesn't address why the octothorpe (
#) sigil was chosen.I would think the js community would prefer the underscore (
_) which is a popular convention used to denote private member variables in current code as well as python and other languages.kitsonk commentedon Jun 20, 2017
The problem is that would break the internet, because the runtime engine must lookup the property differently. If every
_foosuddenly became truly private, imagine the horror. The sigil must be something that isn't currently a valid identifier in JavaScript to ensure that nothing breaks.littledan commentedon Jun 20, 2017
Steven (@styfle) This is a great point. I added a new FAQ entry to explain the reasoning.
styfle commentedon Jun 20, 2017
Daniel Ehrenberg (@littledan) Excellent, thank you for the detailed write up! I submitted a PR with some typo fixes.
I noticed the proposal-private-fields is Stage 1 but the proposal-class-fields is Stage 2 and seems to include private fields. Is this expected and if so, why?
mihailik commentedon Jun 21, 2017
Why WeakMaps not closures?
littledan commentedon Jun 21, 2017
mihailik Because there's still just one method identity on the prototype, rather than the instance.
mihailik commentedon Jun 21, 2017
A rough prototype (play with it on CodePen)
littledan commentedon Jun 21, 2017
Bound methods are being pursued separately, cc Ron Buckton (@rbuckton)
In some engines, using bound methods all the time is slower. Anyway, ES6
classdoes not have bound methods. Ordinary methods should be able to read private fields without suddenly switching into an entirely different mode, right?mihailik commentedon Jun 21, 2017
Having to re-bind methods for each instance is the cost of implementation using closures.
Is WeakMap implementation cheaper? Not obvious. Especially considering nontrivial performance/GC/JIT pressures of WeakMap.
Closure implementation has another win: it works on ES5 too.
mihailik commentedon Jun 21, 2017
Besides, the approach works when emitting ES6 classes too (again, CodePen to try):
littledan commentedon Jun 21, 2017
If you're talking about how TypeScript should implement this, then the desugaring you have there has observably different semantics than the spec. In particular, you can
.calla method which uses private state on a different receiver.If you're talking about what semantics to adopt to be efficiently implementable: WeakMaps in V8 aren't the fastest, but private fields will allow implementation with V8's internal-only "private symbols", which are more efficient. Not sure about other engines.
mihailik commentedon Jun 21, 2017
True! Desugaring is already observably different of course — so it's a matter of weighing pros and cons.
Besides, I think the whole approach may be worth considering in JS spec as well. Using
privatekeyword instead of '#' and making class methods accesses "tinted" so for anyX.Yaccess the runtime would check ifXis the same class andYis a field/method declared asprivate.It's more complex in the engine, but much benefit for the coders, and more sane mental model.
littledan commentedon Jun 21, 2017
This isn't an engine issue, it's a language design issue. Please refer to the private fields FAQ to find documentation for the design.
I hope the TypeScript team tries to minimize observable differences, though I understand this isn't always possible. If differences are minimized, there will be a smaller "bump" for users who come from or to standard JS. In this case, which receiver is used is a pretty big difference.
mihailik commentedon Jun 21, 2017
Daniel Ehrenberg (@littledan) out curiosity, in which practical case you expect this be observed? In which cases do people define methods on a class, only to bind it to something else?
The JS FAQ is cautious on
privatekeyword due to complexity of VM implementation, not because language or mental model is hard. I don't think it's easy to find a JS user who would prefer the hash toprivate.kitsonk commentedon Jun 21, 2017
There is extensive discussion of this in the TC39 proposal. No good re-hashing it here, on an issue about the TypeScript implementation of the proposal. It would be best to focus the discussion in the proper forum, which considers the matter closed.
RyanCavanaugh commentedon Jun 21, 2017
As usual I'd echo what Kitson Kelly (@kitsonk) just said
mihailik commentedon Jun 21, 2017
My closure-based suggestion is related to TypeScript. Any comments on that, regardless of JS implementation?
littledan commentedon Jul 3, 2017
mihailik I'd encourage TypeScript to not use that kind of closure-based implementation, since it'd diverge from the possible native implementations in a pretty major way. TypeScript users may start depending on this behavior and be disappointed when they have to change their code later.