{"action":"created","issue":{"url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/106","repository_url":"https://api.github.com/repos/tc39/proposal-class-fields","labels_url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/106/labels{/name}","comments_url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/106/comments","events_url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/106/events","html_url":"https://github.com/tc39/proposal-class-fields/issues/106","id":332477376,"node_id":"MDU6SXNzdWUzMzI0NzczNzY=","number":106,"title":"Private members break proxies","user":{"login":"jods4","id":3832820,"node_id":"MDQ6VXNlcjM4MzI4MjA=","avatar_url":"https://avatars2.githubusercontent.com/u/3832820?v=4","gravatar_id":"","url":"https://api.github.com/users/jods4","html_url":"https://github.com/jods4","followers_url":"https://api.github.com/users/jods4/followers","following_url":"https://api.github.com/users/jods4/following{/other_user}","gists_url":"https://api.github.com/users/jods4/gists{/gist_id}","starred_url":"https://api.github.com/users/jods4/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jods4/subscriptions","organizations_url":"https://api.github.com/users/jods4/orgs","repos_url":"https://api.github.com/users/jods4/repos","events_url":"https://api.github.com/users/jods4/events{/privacy}","received_events_url":"https://api.github.com/users/jods4/received_events","type":"User","site_admin":false},"labels":[{"id":988247143,"node_id":"MDU6TGFiZWw5ODgyNDcxNDM=","url":"https://api.github.com/repos/tc39/proposal-class-fields/labels/semantics","name":"semantics","color":"dda458","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":129,"created_at":"2018-06-14T16:32:02Z","updated_at":"2018-07-09T19:03:32Z","closed_at":null,"author_association":"NONE","body":"I commented on an old issue in tc39/proposal-private-fields#102 but after reading the answer I feel like I should re-open an issue.\r\n\r\nIt's been discussed before: current `PrivateName` spec doesn't tunnel through proxies.\r\nIn my opinion the consequences have been under-evaluated.\r\n\r\nProxies are already quirky: they don't work with internal slots (bye `Number`, `Date`, `Promise` and friends), they change the identity of `this` (no equality, no `WeakMap`).\r\nBut at least, they work on classes.\r\n\r\nSo they are useful. Libraries and frameworks can provide many features that motivated building proxies: automatic logging, lazy objects, dependency detection and change tracking.\r\n\r\nMy point here is that `PrivateName` and `Proxy` don't work together. You have to choose one of the two features and give up on the other. Partitionning JS features in this way is terrible.\r\n\r\nHere is a basic example.\r\nLet's say a library provides `logReads`, a function that writes on the console every member that is read.\r\n```js\r\nfunction logReads(target) { \r\n  return new Proxy(target, {\r\n    get (obj, prop, receiver) {\r\n      console.log(prop);\r\n      return target[prop];\r\n    },\r\n  });\r\n}\r\n```\r\n\r\nNow let's say I'm writing an application and I use private fields for encapsulation, because they're nice.\r\n```js\r\nclass TodoList {\r\n  #items = [];\r\n  threshold = 50;\r\n\r\n  countCheap() {\r\n    return this.#items.reduce((n, item) => item.price < this.threshold ? n : n + 1, 0);\r\n  }\r\n}\r\n```\r\n\r\nI would like to use that nice logging library to better understand what happens when I run my code.\r\nSeems legit from a naive user's perspective:\r\n```js\r\nlet list = logReads(new TodoList);\r\nlist.countCheap(); // BOOOM\r\n```\r\nAhaha gotcha! And if you don't know the source code, why it crashes when inside a proxy might be a unpleasant mystery.\r\n\r\nPlease reconsider. All it takes to solve this is make `PrivateName` tunnel through proxy (no interception, encapsulation is fine).\r\n\r\nDon't think that returning bound functions from the proxy will solve this. It might seem better but creates many new issues of its own."},"comment":{"url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/comments/403586485","html_url":"https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-403586485","issue_url":"https://api.github.com/repos/tc39/proposal-class-fields/issues/106","id":403586485,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMzU4NjQ4NQ==","user":{"login":"zenparsing","id":5995084,"node_id":"MDQ6VXNlcjU5OTUwODQ=","avatar_url":"https://avatars1.githubusercontent.com/u/5995084?v=4","gravatar_id":"","url":"https://api.github.com/users/zenparsing","html_url":"https://github.com/zenparsing","followers_url":"https://api.github.com/users/zenparsing/followers","following_url":"https://api.github.com/users/zenparsing/following{/other_user}","gists_url":"https://api.github.com/users/zenparsing/gists{/gist_id}","starred_url":"https://api.github.com/users/zenparsing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zenparsing/subscriptions","organizations_url":"https://api.github.com/users/zenparsing/orgs","repos_url":"https://api.github.com/users/zenparsing/repos","events_url":"https://api.github.com/users/zenparsing/events{/privacy}","received_events_url":"https://api.github.com/users/zenparsing/received_events","type":"User","site_admin":false},"created_at":"2018-07-09T19:03:32Z","updated_at":"2018-07-09T19:03:32Z","author_association":"NONE","body":"Apologies in advance for the length...\r\n\r\n> I don't share the intuition that syntax obscures the semantics that WeakMap is supposed to make obvious, in that there are multiple subtle semantics at play here. \r\n\r\n\"We should not bother making things simple\" does not follow from \"things are complex\".\r\n\r\n> Opt-in per-Proxy tunneling is a simple solution that irons out the internal slots quirk.\r\n\r\n**If** we are going to go that route after all, then I wonder why we aren't just using private symbols. It is a far less obtrusive solution, both syntactically and semantically.\r\n\r\nAt a higher level, how many turtles are we going to have to stack up to make private syntax work? So far we have:\r\n\r\n1. Private fields, with a syntax no one likes, that sucks up one of the last 2 remaining ASCII chars.\r\n2. Private methods, because of the lexical scoping restrictions of (1), that look syntactically like prototype properties but aren't really.\r\n3. Private static fields, because it seems weird to have (1) and not (3).\r\n\r\nAnd we'll probably end up with a few more:\r\n\r\n4. Transparent proxies, because (1) doesn't work well with existing proxies.\r\n5. Static class initializer blocks, because we want to push (1) into outer scopes.\r\n6. `#` support in destructuring patterns, because users will expect it given existing programming idioms.\r\n7. `class.x` syntax to get around the \"static private this\" hazard.\r\n8. `#` support in object literals, because it's in the destructuring grammar, and because we don't really want classes to be special.\r\n\r\nAfter all of this, we will have vastly altered the language. Will it have been worth it? Contrast with abstract refs:\r\n\r\n1. Add `::` support to WeakMaps (or PrivateMap, or whatever)\r\n1. Add `::` support to functions for doing \"hidden\" method stuff\r\n\r\nDone. (The assumption being that hard privacy is only used in the specific cases that require it - i.e. don't break reflection unless you **really** mean it.)\r\n\r\nHow can we determine whether the relatively large cost of private syntax is worth it, given less costly alternatives?\r\n"}}
{"actor":{"display_login":"zenparsing"}}