Re: Why can't the left-hand side of an assignment expression use optional chaining?

2020-07-14 Thread #!/JoePea
There's a good number of upvotes for it. It would be nice.
#!/JoePea

On Thu, Apr 30, 2020 at 1:13 PM Jordan Harband  wrote:
>
> See https://github.com/tc39/proposal-optional-chaining/issues/18
>
> On Thu, Apr 30, 2020 at 1:08 PM #!/JoePea  wrote:
>>
>> I was hoping to avoid things like
>>
>> ```js
>> const baz = this.foo?.bar?.baz
>> if (baz) baz.lorem = 123
>> ```
>>
>> #!/JoePea
>>
>> On Thu, Apr 30, 2020 at 1:04 PM #!/JoePea  wrote:
>> >
>> > This is perfectly fine:
>> >
>> > ```js
>> > this.foo?.bar?.setBaz(123)
>> > ```
>> >
>> > but this is not:
>> >
>> > ```js
>> > this.foo?.bar?.baz = 123
>> > ```
>> >
>> > Why is that not allowed, but function calls are?
>> >
>> > I find myself often wanting to do assignments like that. When I am
>> > auto-completing things in VS Code (TypeScript), it automatically and
>> > awesomely inserts the `?` characters, only to fail once I write the
>> > assignment part.
>> >
>> > #!/JoePea
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Are ES Modules garbage collected? If so, do they re-execute on next import?

2020-07-14 Thread #!/JoePea
How can we ensure that long-running applications (even if theoretical),
that may load and unload an unlimited number of new modules over time
(f.e. routes in a web page specified by 3rd parties as time
progresses), not leak memory?

Even if it is theoretical, I don't like the thought of something that
only ever allocates memory that will never be freed.

Is someone working on a solution for this?


#!/JoePea

On Wed, Jul 1, 2020 at 6:16 AM Mark S. Miller  wrote:
>
> No, definitely not. The table from specifiers to module instances is indexed 
> by specifiers. Specifiers are strings, so this table is not weak. It is not a 
> "cache" in the sense that it is allowed to drop things. Rather it is a 
> registry of module instances. Only a registry as a whole can be gc'ed, and 
> which point that context is no longer around for instantiating or 
> reinstantiating modules.
>
> As you suggest, if it could drop things because of GC that it would then need 
> to regenerate, that would expose the non-determinism of gc. That would be a 
> big deal. We carefully designed WeakMaps so that gc was non-observable. 
> WeakMaps introduce no observable non-determinism. WeakRefs alone expose the 
> non-determinism of gc, and are kept well quarantined from the rest of the 
> language.
>
>
> On Tue, Jun 30, 2020 at 5:42 PM #!/JoePea  wrote:
>>
>> I am curious: can modules be garbage collected if the exports are not
>> references by anything anymore? And if so, will the module be
>> re-evaluated the next time it is imported?
>>
>> I haven't tried an experiment to answer this yet. I'll be back to post
>> findings if someone doesn't post an official answer first.
>>
>> I'm thinking about code longevity. For example, if we make
>> long-running web-based applications with many routes and features (for
>> sake of example imagine a desktop environment, or a MMORPG game, with
>> apps or components that are loaded within the same context). Over
>> time, if imports are not collected, then it means we have a memory
>> leak.
>>
>> Imagine, for example, an infinite-universe MMORPG where you can land
>> on different planets where the code for features of a planet are
>> provided by third parties as ES Modules. I know, this might not be a
>> safe idea to import any code into an app, but just imagine it for sake
>> of example (imagine we have a continuous integration system to test
>> and verify code security, or something, before that code is allowed to
>> be consumed in the app). Imagine you play this app for many many days,
>> and visit many places, and you leave the app running the whole time
>> (because farming for resources is disabled if the app is not running,
>> or something).
>>
>> I would imagine that we want unused modules (when we leave a planet,
>> for example) to be (destroyed) garbage collected so that we don't
>> waste memory.
>>
>> #!/JoePea
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> --
>   Cheers,
>   --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Any way to detect an async stack trace (like Chrome devtools does)?

2020-07-14 Thread #!/JoePea
> The way promises are chained means that some patterns like async loops would 
> theoretically unroll to very long stack traces

Devtools in fact does that (has a button at the bottom of the stack to
keep loading more frames).

I think it would be better for it to be smart and not have duplicate
frames in the stack, so a loop would result in only one unique set of
entries in the stack trace and not repeat.

#!/JoePea

On Sun, Jul 12, 2020 at 11:53 AM Jacob Bloom  wrote:
>
> Reading through the issue JoePea linked to, it looks like the difficulties 
> with standardized async stack traces are twofold:
>
> 1. Even with the error stacks proposal, the implementer has total say over 
> what qualifies as a stack frame
> 2. The way promises are chained means that some patterns like async loops 
> would theoretically unroll to very long stack traces, and right now engines 
> aren't required to keep track of those frames; requiring them to do so would 
> place a burden on implementers that could quickly lead to slowdowns and 
> memory issues
>
> What if there was a standard way to mark a Promise as an important stack 
> frame, which the implementer is free to ignore? Maybe something like 
> `Promise.prototype.trace()`
>
> On Fri, Jul 10, 2020 at 10:22 PM #!/JoePea  wrote:
>>
>> Hello Kai! That example is so meta with its own output showing the
>> numbers relative to the code including its own output! :)
>>
>> That's what I originally wanted to do, but that doesn't give us an
>> async stack trace, it only gives a sync stack trace (I presume within
>> the current event loop task).
>>
>> For example:
>>
>> ```js
>> const originalFetch = globalThis.fetch
>>
>> globalThis.fetch = function(...args) {
>>   const stack = new Error().stack
>>   console.log(stack)
>>   return originalFetch.apply(globalThis, args)
>> }
>>
>> const sleep = t => new Promise(r => setTimeout(r, t))
>>
>> async function one() {
>>   console.log('1')
>>   await sleep(10)
>>   two()
>> }
>>
>> async function two() {
>>   console.log('2')
>>   await sleep(10)
>>   three()
>> }
>>
>> async function three() {
>>   console.log('3')
>>   await sleep(10)
>>   return await fetch('https://unpkg.com/three@0.118.3')
>> }
>>
>> async function main() {
>>   await one()
>> }
>>
>> main()
>> ```
>>
>> Output:
>>
>> ```
>> 1
>> 2
>> 3
>> Error
>> at globalThis.fetch (pen.js:5)
>> at three (pen.js:27)
>> ```
>>
>> Live example:
>>
>> https://codepen.io/trusktr/pen/b8fd92752b4671268f516ad3804869e4?editors=1010
>>
>> I opened a request for this over here:
>> https://github.com/tc39/proposal-error-stacks/issues/34
>>
>> #!/JoePea
>>
>> On Fri, Jul 10, 2020 at 1:21 PM kai zhu  wrote:
>> >
>> > >  (I want to detect traces in third-party code installed locally).
>> >
>> > 1. here's 15-line javascript-hack to trace async-fetch-calls from 
>> > 3rd-party-cdn-library
>> >
>> > ```html
>> > 
>> > 
>> > 
>> > test.html
>> > 
>> > (function () {
>> > /*
>> >  * 15-line-javascript-hack to trace async-fetch-calls
>> >  * enable hack by adding search-query "?modeDebugFetch=1" to web-url
>> >  */
>> > "use strict";
>> > if ((/\bmodeDebugFetch=1\b/).test(location.search)) {
>> > let fetch0;
>> > fetch0 = globalThis.fetch;
>> > globalThis.fetch = function (...argList) {
>> > let errStack = new Error().stack;
>> > console.error("\n\nfetch-call-arguments:");
>> > console.error(JSON.stringify(argList, undefined, 4));
>> > console.error("\n\nfetch-call-trace:");
>> > console.error(errStack);
>> > return fetch0(...argList);
>> > };
>> > }
>> > }());
>> > 
>> > 
>> > https://unpkg.com/http-client/umd/http-client.js";>
>> > 
>> > (async function foo() {
>> > "use strict";
>> > let thirdParty = window.HTTPClient;
>> > let myFetch = thirdParty.createFetch(
>> > thirdParty.base("https://api.stripe.com/v1";),
>> > thirdParty.accept("application/json")
>> > );
>> > let response = await myFetch("/customers/5");
>> > console.log(response.jsonData);
>> > /*
>> > dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1
>> > fetch-call-arguments:
>> > [
>> > "https://api.stripe.com/v1/customers/5";,
>> > {
>> > "headers": {
>> > "Accept": "application/json"
>> > },
>> > "responseHandlers": [
>> > null
>> > ]
>> > }
>> > ]
>> > fetch-call-trace:
>> > Error
>> > at globalThis.fetch (test.html?modeDebugFetch=1:16)
>> > at http-client.js:194
>> > at http-client.js:127
>> > at http-client.js:217
>> > at http-client.js:126
>> > at http-client.js:154
>> > at http-client.js:95
>> > at foo 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-14 Thread #!/JoePea
>  private members (safely) allow classes with internal slots.

I'd say that they aren't safe, if they can break 3rd-party code on the
external public side.

#!/JoePea

On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
 wrote:
>
> I assume OP wants to use proxies and private members together. They are not 
> designed to be compatible.
>
> Proxies and private members are a UX goal primarily for developers. Proxies 
> easily allow observation of another object or creation of exotic objects 
> (e.g. Array), and private members (safely) allow classes with internal slots. 
> Since they cannot be used together the issue exists, and the hack circumvents 
> this by reimplementing private in a way that does not require private fields.
>
> On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>>
>> as product-developer, can i ask what ux-objective you ultimately want 
>> achieved?
>>
>> ```js
>> const sub = new Sub()
>>
>> // i'm a noob on proxies. what is this thing (with proxied-private-fields) 
>> ultimately used for?
>> const proxy = new Proxy(sub, ...)
>> ```
>>
>> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>>  wrote:
>>>
>>> This does require you to have both the key and the weakmap though, so it 
>>> actually does succeed in hiding the data so long as the weakmap is out of 
>>> scope. I guess the issue I can foresee is that the key could be modified 
>>> after the object is created.
>>>
>>> e.g.
>>> ```js
>>> var a = new A();
>>> var key = Object.getOwnPropertySymbols(a)[0];
>>> delete a[key];
>>> a.hidden; // throws
>>> ```
>>>
>>> That itself can be guarded by just making the key undeletable. So, I guess 
>>> this solution could work depending what your goals are?
>>>
>>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>>>  wrote:

 It nearly works, but the issue is that the key will be leaked by 
 `Object.getOwnPropertySymbols(new A())`, so it's not truly private.

 There have been ideas proposing "private symbols" but I am not familiar 
 with their issues, and I would guess with Class Fields they are unlikely 
 to materialize anyway.

 On Sun, Jul 12, 2020 at 2:19 PM François REMY 
  wrote:
>
> At the risk of pointing out the obvious:
>
>
>
> ```js
>
> const privkey = Symbol();
>
> const stores = new WeakMap();
>
>
>
> class A {
>
>   [privkey] = {};
>
>   constructor() {
>
> const priv = {};
>
> priv.hidden = Math.random();
>
> stores.set(this[privkey], priv);
>
>   }
>
>
>
>   get hidden() {
>
> const priv = stores.get(this[privkey]);
>
> return priv.hidden;
>
>   }
>
> }
>
>
>
> var as = [
>
> new A(),
>
> new Proxy(new A(),{}),
>
> new Proxy(new A(),{}),
>
> ];
>
> console.log(as.map(a=>a.hidden));
>
> ```
>
>
>
>
>
>
>
> From: Michael Theriot
> Sent: Sunday, July 12, 2020 20:59
> To: Michael Haufe
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I experienced this issue prior to this proposal, using weakmaps for 
> private access.
>
>
>
> e.g.
>
> ```js
>
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>   }
>
>   get hidden() {
> const priv = stores.get(this);
> return priv.hidden;
>   }
> }
>
> const a = new A();
> console.log(a.hidden); // 0
>
> const p = new Proxy(a, {});
> console.log(p.hidden); // throws!
>
> ```
>
>
>
> I found a workaround:
>
>
>
> ```js
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>
> const p = new Proxy(this, {});
> stores.set(p, priv); // set proxy to map to the same private store
>
> return p;
>   }
>
>   get hidden() {
> const priv = stores.get(this); // the original instance and proxy 
> both map to the same private store now
> return priv.hidden;
>   }
> }
>
> const a = new A();
>
> console.log(a.hidden);
> ```
>
>
>
> Not ideal, and only works if you provide the proxy in the first place 
> (e.g. making exotic JS objects). But, not necessarily a new issue with 
> proxies, either.
>
>
>
> On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe  
> wrote:
>
> This is a known issue and very painful for me as well. You can see a long 
> ugly discussion here:
>
>
>
> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-14 Thread #!/JoePea
>TC39 choose (correctly, I think) in favor of secure field privacy. The lesser 
>evil choice.”

The PrivateField tunneling that was talked about in that issue would
not expose any privacy. The fact that external proxies break when
internal code introduces a private field is _actually_ leaking
privacy.

TC39 did not choose in favor of privacy, they chose to leave a feature
out and make private fields less private than they should be.

> With that being said workarounds have already been presented:

Those workaround only work in certain cases, namely when you control
the proxy and then give it to external code, or if you tell all your
users to make sure they write proxy membranes for all your methods
(ouch!).

A true solution would leave all existing code working as-is, and would
never break if internal code introduced a private field.

#!/JoePea

On Sun, Jul 12, 2020 at 3:17 PM Michael Haufe  wrote:
>
> To quote from a short conversation I had with Allen Wirfs-Brock:
>
>
>
> “Proxies have a similar issue WRT the "internal slots" of built-ins. The 
> alternatives were the non-othogonality with Proxy or private fields whose 
> privacy was insecure. TC39 choose (correctly, I think) in favor of secure 
> field privacy. The lesser evil choice.”
>
>
>
> With that being said workarounds have already been presented:
>
>
>
> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
>
> https://javascript.info/proxy#private-fields
>
>
>
>
>
>
>
> From: es-discuss  On Behalf Of Michael Theriot
> Sent: Sunday, July 12, 2020 5:10 PM
> To: kai zhu 
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I assume OP wants to use proxies and private members together. They are not 
> designed to be compatible.
>
>
>
> Proxies and private members are a UX goal primarily for developers. Proxies 
> easily allow observation of another object or creation of exotic objects 
> (e.g. Array), and private members (safely) allow classes with internal slots. 
> Since they cannot be used together the issue exists, and the hack circumvents 
> this by reimplementing private in a way that does not require private fields.
>
>
>
> On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>
> as product-developer, can i ask what ux-objective you ultimately want 
> achieved?
>
>
>
> ```js
>
> const sub = new Sub()
>
>
>
> // i'm a noob on proxies. what is this thing (with proxied-private-fields) 
> ultimately used for?
>
> const proxy = new Proxy(sub, ...)
>
> ```
>
>
>
> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>  wrote:
>
> This does require you to have both the key and the weakmap though, so it 
> actually does succeed in hiding the data so long as the weakmap is out of 
> scope. I guess the issue I can foresee is that the key could be modified 
> after the object is created.
>
>
>
> e.g.
>
> ```js
>
> var a = new A();
>
> var key = Object.getOwnPropertySymbols(a)[0];
> delete a[key];
>
> a.hidden; // throws
>
> ```
>
>
>
> That itself can be guarded by just making the key undeletable. So, I guess 
> this solution could work depending what your goals are?
>
>
>
> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>  wrote:
>
> It nearly works, but the issue is that the key will be leaked by 
> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>
>
>
> There have been ideas proposing "private symbols" but I am not familiar with 
> their issues, and I would guess with Class Fields they are unlikely to 
> materialize anyway.
>
>
>
> On Sun, Jul 12, 2020 at 2:19 PM François REMY  
> wrote:
>
> At the risk of pointing out the obvious:
>
>
>
> ```js
>
> const privkey = Symbol();
>
> const stores = new WeakMap();
>
>
>
> class A {
>
>   [privkey] = {};
>
>   constructor() {
>
> const priv = {};
>
> priv.hidden = Math.random();
>
> stores.set(this[privkey], priv);
>
>   }
>
>
>
>   get hidden() {
>
> const priv = stores.get(this[privkey]);
>
> return priv.hidden;
>
>   }
>
> }
>
>
>
> var as = [
>
> new A(),
>
> new Proxy(new A(),{}),
>
> new Proxy(new A(),{}),
>
> ];
>
> console.log(as.map(a=>a.hidden));
>
> ```
>
>
>
>
>
>
>
> From: Michael Theriot
> Sent: Sunday, July 12, 2020 20:59
> To: Michael Haufe
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I experienced this issue prior to this proposal, using weakmaps for private 
> access.
>
>
>
> e.g.
>
> ```js
>
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>   }
>
>   get hidden() {
> const priv = stores.get(this);
> return priv.hidden;
>   }
> }
>
> const a = new A();
> console.log(a.hidden); // 0
>
> const p = new Proxy(a, {});
> console.log(p.hidden); // throws!
>
> ```
>
>
>
> I found a workaround:
>
>
>
> ```js
> const stores = new