Re: Destructuring by

2021-03-03 Thread #!/JoePea
Or maybe it would be

```js
theFunction(obj., obj.);
```

to explicitly pass the particular properties, and would account for
nested properties too:

```js
theFunction(obj.foo., obj.lorem.);
```

#!/JoePea

On Wed, Mar 3, 2021 at 6:29 PM #!/JoePea  wrote:
>
> I think it is a good idea, but maybe we need to think about what the
> final syntax would be. About segregation, if the library changes the
> signature, then they'll have the whole source object, right? Maybe for
> the mentioned security the user would need to opt in:
>
> ```js
> theFunction(, );
> ```
>
> would allow the function to destructure, and only destructure, by
> reference of those given properties, for example. Then the contract
> can not silently change from secure to insecure.
>
> #!/JoePea
>
> On Wed, Mar 3, 2021 at 9:47 AM Andrea Giammarchi
>  wrote:
> >
> > to expand further: you *could* access such reference via `arguments[0]`, 
> > but *that* won't be possible with arrow functions, as example, so that 
> > `({}, maybe) => { if (maybe) reactive = true; }` is another 
> > pattern that doesn't need the whole object around, or to be propagated, 
> > when you can pass it via `{}` to anything else, covering then the 
> > `arguments` point too.
> >
> > On Wed, Mar 3, 2021 at 6:44 PM Andrea Giammarchi 
> >  wrote:
> >>
> >> > the proposal is just a debatable syntax sugar for something we already 
> >> > can do
> >>
> >> that's basically the entirety of the syntax sugar proposals since ES2015, 
> >> right? also proxy and globalThis are *really* unrelated to this, imho, 
> >> while leaking objects all over down the pipe is my major concern, 
> >> something this proposal avoids, as no code will have a reference to the 
> >> entirety of the source object, they'll deal with a known property name 
> >> passed by reference, incapable of changing anything else in the source 
> >> object ... so it's rather a signal, than a convention.
> >>
> >> this means composability, different classes/prototypes passed as 
> >> arguments, and the certainty nothing can inspect, change, or deal, with 
> >> the source, which means increased security, as opposite to pass instances 
> >> and whole objects references around.
> >>
> >> You have a reference to a property, you don't see its source.
> >>
> >>
> >> On Wed, Mar 3, 2021 at 6:19 PM Augusto Moura  
> >> wrote:
> >>>
> >>> > ```js
> >>> > function stuff(source, extra) {
> >>> >   const {value, method} = source;
> >>> >
> >>> >   if (condition)
> >>> > method.call(source);
> >>> >
> >>> >   if (value === extra)
> >>> > source.value = 'no more';
> >>> > }
> >>> > ```
> >>>
> >>> I mean, in this case you can skip destructuring altogether, having a one 
> >>> way and way only of value indirection is a Pretty Good Thing™ (even 
> >>> though we already have proxys, globalThis and other indirection 
> >>> shenanigans), I never felt annoyed of just using `source.value` or 
> >>> `source.method()` instead of `value` and `method()`, again the proposal 
> >>> is just a debatable syntax sugar for something we already can do. I 
> >>> wonder if we could ever do the reference thingy in user-land with 
> >>> variable level decorators, if it ever gets discussed again in the 
> >>> meetings. Would be still kinda fishy to propose and implement
> >
> > ___
> > 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: Destructuring by

2021-03-03 Thread #!/JoePea
I think it is a good idea, but maybe we need to think about what the
final syntax would be. About segregation, if the library changes the
signature, then they'll have the whole source object, right? Maybe for
the mentioned security the user would need to opt in:

```js
theFunction(, );
```

would allow the function to destructure, and only destructure, by
reference of those given properties, for example. Then the contract
can not silently change from secure to insecure.

#!/JoePea

On Wed, Mar 3, 2021 at 9:47 AM Andrea Giammarchi
 wrote:
>
> to expand further: you *could* access such reference via `arguments[0]`, but 
> *that* won't be possible with arrow functions, as example, so that 
> `({}, maybe) => { if (maybe) reactive = true; }` is another pattern 
> that doesn't need the whole object around, or to be propagated, when you can 
> pass it via `{}` to anything else, covering then the `arguments` 
> point too.
>
> On Wed, Mar 3, 2021 at 6:44 PM Andrea Giammarchi 
>  wrote:
>>
>> > the proposal is just a debatable syntax sugar for something we already can 
>> > do
>>
>> that's basically the entirety of the syntax sugar proposals since ES2015, 
>> right? also proxy and globalThis are *really* unrelated to this, imho, while 
>> leaking objects all over down the pipe is my major concern, something this 
>> proposal avoids, as no code will have a reference to the entirety of the 
>> source object, they'll deal with a known property name passed by reference, 
>> incapable of changing anything else in the source object ... so it's rather 
>> a signal, than a convention.
>>
>> this means composability, different classes/prototypes passed as arguments, 
>> and the certainty nothing can inspect, change, or deal, with the source, 
>> which means increased security, as opposite to pass instances and whole 
>> objects references around.
>>
>> You have a reference to a property, you don't see its source.
>>
>>
>> On Wed, Mar 3, 2021 at 6:19 PM Augusto Moura  
>> wrote:
>>>
>>> > ```js
>>> > function stuff(source, extra) {
>>> >   const {value, method} = source;
>>> >
>>> >   if (condition)
>>> > method.call(source);
>>> >
>>> >   if (value === extra)
>>> > source.value = 'no more';
>>> > }
>>> > ```
>>>
>>> I mean, in this case you can skip destructuring altogether, having a one 
>>> way and way only of value indirection is a Pretty Good Thing™ (even though 
>>> we already have proxys, globalThis and other indirection shenanigans), I 
>>> never felt annoyed of just using `source.value` or `source.method()` 
>>> instead of `value` and `method()`, again the proposal is just a debatable 
>>> syntax sugar for something we already can do. I wonder if we could ever do 
>>> the reference thingy in user-land with variable level decorators, if it 
>>> ever gets discussed again in the meetings. Would be still kinda fishy to 
>>> propose and implement
>
> ___
> 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: Why does Object.keys return an Array instead of a Set?

2020-10-26 Thread #!/JoePea
Interesting, on my system I consistently see Set iteration is faster
(I replayed it many times). I'm in Chrome 85, Linux. This might be
temporary.

> `new Set(Object.keys(obj))`

That creates two objects and an iteration (will the engine optimize
that away?), while `Object.keySet` (or similar) would surely create a
single object.

#!/JoePea

On Sun, Oct 18, 2020 at 10:19 AM Jordan Harband  wrote:
>
> `new Set(Object.keys(obj))` seems pretty straightforward - I doubt it's worth 
> adding something to the language just to make that shorter.
>
> Separately, if you're looking for a deduped O(1) lookup of key presence, you 
> already have _an object_ - `Object.prototype.hasOwnProperty.call(obj, key)`.
>
> On Sun, Oct 18, 2020 at 8:28 AM Ehab Alsharif  wrote:
>>
>> Other than the fact that Object.keys existed really before Sets, you are 
>> comparing apples and oranges here in your benchmarks.
>> the include method has to scan the array in order to find elements, but sets 
>> are objects which are just hash tables.
>> Also you typically don't get the keys array to check that a key is there, 
>> you can do that directly using the object you have.
>> Another thing is that the typical use case for Object.keys is to get an 
>> iterator over the keys, returning a set for that purpose does not serve that 
>> purpose directly.
>>
>> On Sat, Oct 17, 2020 at 4:51 AM #!/JoePea  wrote:
>>>
>>> Sets are faster, even for tiny lists of four items. See the perf tests
>>> (tested in Chrome):
>>>
>>> https://twitter.com/trusktr/status/1315848017535098880
>>>
>>> https://twitter.com/trusktr/status/1317281652540731392
>>>
>>> #!/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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-22 Thread #!/JoePea
>  It's caused me some headaches especially when dealing with 
> inheritance/extends and in workers.

Like, extending from a `Module` object?

> Maybe someday we'll have a `modules` collection we can interrogate.

That may be nice, to query which modules have already been imported, etc.

It would also be great if we could unload modules.

---

Skypack is making news rounds as an ESM server: http://skypack.dev/

It says it supports HTTP/2 and HTTP/3. But it isn't open source.

Seems that there isn't any open source solution (otherwise I'm sure
people would be using that over bundling if it works out better, at
least alternatives to skypack would exist, f.e. well-know projects
like React, Angular, Vue, Svelte, etc, could all have their own ES
Module servers if it was viable).

Seems that there hasn't been any free/open project to prove viability
yet, and the existing ones are closed source.

Seems that even http://jspm.dev is closed source.

Looks like at this point in time people are aiming to make money from
ESM servers, and there's no viable open source ESM server solution.

#!/JoePea

On Sun, Oct 18, 2020 at 8:50 AM Randy Buchholz  wrote:
>
> Right, it's basically just doing what an import aware server might do and the 
> type-tree is a hierarchal version of the scope imports. The rest is just 
> extra stuff. Probably the biggest difference though is that it lets me 
> isolate prototypes. From what I gather it seems that import stores a live 
> "ghosted" version of the prototype that it checks before making additional 
> requests for the item. The scope basically gets a reference to this 
> prototype. If you do things like add a property with reflect in one scope 
> that property shows up everywhere. And since it modified the "ghost" it 
> persists after the scope goes away. It's caused me some headaches especially 
> when dealing with inheritance/extends and in workers.
>
> Yeah, inspecting is in issue. I haven't found a way to inspect modules to see 
> what they have in them. They're a strange beast. You can see their scope in 
> the debugger and they look like an ES Object or IDL interface, but I don't 
> know how to get a reference to them in code. But, they're new, so we'll see 
> where they go. Maybe someday we'll have a `modules` collection we can 
> interrogate.
>
> -Original Message-
> From: #!/JoePea 
> Sent: Saturday, October 17, 2020 10:35 PM
> To: Randy Buchholz 
> Cc: es-discuss@mozilla.org
> Subject: Re: Are ES6 modules in browsers going to get loaded level-by-level?
>
> That's neat, but it seems like the same work that a server would have to do 
> with actual ES Module imports, right? And the "type tree"
> equivalent is the modules that the JS engine stores as a map from import 
> identifier to module scope instance. It seems that in the end, the `PUSH` 
> approach should work with the same efficiency, right?
>
> Seems the only thing that makes it difficult is checking the map. In your 
> special case, with `inject`, you can physically check the global namespaces 
> to see if the module is available. But with ES Modules, we can't check if 
> some module has already been lodade by its identifier, can we? So we have to 
> make the request, because that's the only way to check.
>
> #!/JoePea
>
> On Sat, Oct 17, 2020 at 1:28 PM Randy Buchholz  wrote:
> >
> > I think some form of bundling will always be necessary. I use classes and 
> > took a name-spaced and typed approach to modules and classes, putting each 
> > class in its own module in a file hierarchy (namespace). This is an 
> > enterprise level LOB application with dozens of classes. Many classes are 
> > used cross-domain, limiting static/design-time bundling approaches. Also, 
> > an issue I encountered with static bundling is that classes aren't hoisted, 
> > so there are ordering concerns/issues with class bundles.
> >
> >
> >
> > I have multiple workers as background services that use these. Each class 
> > usually has a few imports for the classes it uses. Using normal imports, I 
> > was soon generating 100's of requests for the files. Even with caching, 
> > there is a lot of overhead. As classes are used more, this can become a 
> > real issue.
> >
> >
> >
> > I ended up with an approach where I added dependency metadata to each class 
> > to support bundling. The metadata helps with the "what to send" issue. When 
> > I need a class/type do an import for it. The server walks the dependencies, 
> > and bundles the request class with the full tree of dependencies. When the 
> > client receives the bundle it adds the new classes to a type library. It's 
> > designed for enterprise use wher

Re: Proposal: Function.prototype.bindContext

2020-10-17 Thread #!/JoePea
I think it's a good idea that would make things more efficient. +1
*#!/*JoePea


On Thu, Sep 17, 2020 at 12:57 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> I'm not sure I'm following, but I'm not here to find solutions, I already
> have solutions, I'm here to propose a new `Function.prototype.bindContext`
> method that doesn't require any user-land discussion/prototype pollution.
>
> Thanks.
>
> On Thu, Sep 17, 2020 at 9:25 PM Adam Eisenreich  wrote:
>
>> This should able to be done via two nested WakMap,
>>
>> First level would be the function and the second the context or vice
>> versa. This should be able to give you the same bound function while both
>> are avaible, but should clear itself once the reference to function/context
>> is lost.
>>
>> -- Původní e-mail --
>> Od: Andrea Giammarchi 
>> Komu: es-discuss@mozilla.org 
>> Datum: 17. 9. 2020 21:03:45
>> Předmět: Proposal: Function.prototype.bindContext
>>
>> I've found myself (once again) polluting the `Function.prototype` with a
>> lazy method that, once invoked, grants that the returned bound function is
>> always the same, per context.
>>
>> # Use Case
>>
>> It's still a common footgun to add events either via `context.method` or
>> via `context.method.bind(context)`, where the former footgan would invoke
>> `method` with a global context/undefined instead of the expected context,
>> while the latter would make it impossible to ever remove that listener
>> later on.
>>
>> It's also common to use methods for timers sensitive things, and it's
>> indeed not by accident that `console` got "self bound", or provided as
>> namespace, when it used to throw if `setTimeout(console.log, 100, value)`
>> was used, for example.
>>
>> # Proposal
>>
>> Provide a lazy `bindContext` method that grants that if a method/function
>> bound the same context before, it always returns the same reference.
>>
>> # Implementation / Polyfill (lazy version)
>>
>> ```js
>> Function.prototype.bindContext = function (context) {
>>   const _ = new WeakMap;
>>   this.bindContext = bindContext;
>>   return bindContext.call(this, context);
>>   function bindContext(context) {
>> if (!_.has(context))
>>   _.set(context, this.bind(context));
>> return _.get(context);
>>   }
>> };
>> ```
>>
>> # Implementation details
>>
>> As the method suggest, and differently from `bind`, `bindContext` accepts
>> only one argument, and it should throw with any context that is primitive
>> (boolean, number, string, undefined, null), like any WeakMap key would
>> throw as well.
>>
>> # Why not user-land / libraries / helpers
>>
>> Because standardizing a well-known/needed utility to not footgun common
>> patterns would make the debate regarding global prototypes pollution
>> irrelevant, as it's the standard that helps us out.
>>
>> In a few words, this might erase tons of common mistakes, but it also
>> could be simplified within some helper/library, as long as not all of them
>> need to include the proposed polyfill through a package or another.
>>
>> Thanks for consideration 
>>
>> ___
>> 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-17 Thread #!/JoePea
That's neat, but it seems like the same work that a server would have
to do with actual ES Module imports, right? And the "type tree"
equivalent is the modules that the JS engine stores as a map from
import identifier to module scope instance. It seems that in the end,
the `PUSH` approach should work with the same efficiency, right?

Seems the only thing that makes it difficult is checking the map. In
your special case, with `inject`, you can physically check the global
namespaces to see if the module is available. But with ES Modules, we
can't check if some module has already been lodade by its identifier,
can we? So we have to make the request, because that's the only way to
check.

#!/JoePea

On Sat, Oct 17, 2020 at 1:28 PM Randy Buchholz  wrote:
>
> I think some form of bundling will always be necessary. I use classes and 
> took a name-spaced and typed approach to modules and classes, putting each 
> class in its own module in a file hierarchy (namespace). This is an 
> enterprise level LOB application with dozens of classes. Many classes are 
> used cross-domain, limiting static/design-time bundling approaches. Also, an 
> issue I encountered with static bundling is that classes aren't hoisted, so 
> there are ordering concerns/issues with class bundles.
>
>
>
> I have multiple workers as background services that use these. Each class 
> usually has a few imports for the classes it uses. Using normal imports, I 
> was soon generating 100's of requests for the files. Even with caching, there 
> is a lot of overhead. As classes are used more, this can become a real issue.
>
>
>
> I ended up with an approach where I added dependency metadata to each class 
> to support bundling. The metadata helps with the "what to send" issue. When I 
> need a class/type do an import for it. The server walks the dependencies, and 
> bundles the request class with the full tree of dependencies. When the client 
> receives the bundle it adds the new classes to a type library. It's designed 
> for enterprise use where you have more control of things and can enforce 
> standards.
>
>
>
> Class looks like this:
>
>
>
> // File Bar.cmjs
>
> ```
>
> //::Requires: Foo.Package.Class1 Foo.Package.Class2
>
> class Bar {
>
> const a = new Class1(); // Actually usually the qualified 
> Foo.Package.Class1
>
> ...
>
> }
>
> ```
>
> // File /Foo/Package/Class1.cmjs
>
> ```
>
> //::/Requires: Common.Util.Whatever
>
> class Class1{
>
>
>
> }
>
> ```
>
>
>
> The basic idea is that when the server gets a request it reads the "Requires" 
> and gets those files, recursively reading requires. I keep a list of all 
> files and the depth so I know if I already captured a required, and how to 
> order the results. Once I have all of the files I write them to a single 
> bundle. I don't need to parse the files (Requires is just a comment), but can 
> if I want more control. The bundled file looks like:
>
>
>
> ```
>
> class Whatever {...}
>
>
>
> class Class1 {...}
>
>
>
> class Class2 {...}
>
>
>
> class Bar {...}
>
> ```
>
>
>
> It's more complex, because of name collisions and import scoping. What I do 
> is process the bundle and promote the classes out of the scope.
>
> ```
>
> globalThis
>
>.Foo
>
>   .Package
>
>  .Class1 = Class1; // (The "newable" class)
>
>  .Class2 = Class2;
>
>.Common
>
>   .Util
>
>  .Whatever = Whatever;
>
> ```
>
>
>
> Now I can just do `new Foo.Package.Class1()` anywhere in the context, not 
> just in the import scope. On the client I use `inject` in many places instead 
> of `import` - inject('A.B.Class'); const x = new A.B.Class();`. This checks 
> for the type, and if it doesn't exist on the client it requests it from the 
> server.  The server creates a bundle for it and its dependencies. I add these 
> to the type-tree. My server isn't really import-aware, I just use middleware 
> to intercept the request. This is why I could use a way to identify "import 
> requests". I know when I’m doing an ”import” through injection, but with a 
> regular import I have to do some inspection of the fetch to know to initiate 
> the process.
>
> ___
> 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: Since JSDoc seems cerebrally dead...

2020-10-17 Thread #!/JoePea
That would be interesting indeed. Encouraging documentation is great I think.
#!/JoePea

On Sat, Oct 17, 2020 at 3:38 AM Michaël Rouges  wrote:
>
> Yeah, I prefer the JSDoc solution too for the same reasons... but JSDoc is 
> really slow to evolve,
> always several years behind the standard, a lot of solutions to describe our 
> code are more relevant
> to **tricks**, generally found on the JSDoc issues, than something formal.
>
> The coverage isn't the same... really, I'm dreaming about a standard 
> annotation for each ES feature,
> covering all the usages. **when that feature is released**.
>
>
> Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
>
>
> Le sam. 17 oct. 2020 à 03:29, #!/JoePea  a écrit :
>>
>> Would official syntax be worth it (JSDoc being officially standardized)?
>>
>> Maybe it's a matter of time: Perhaps now that JSDoc is useful for type
>> checking (thanks to TypeScript and its ability to type check plain
>> JavaScript that is annotated with JSDoc) it may be closer to reality.
>>
>> I prefer JSDoc type annotation in plain .js files over writing .ts
>> files, because it means I can write type-checked code that has great
>> intellisense in modern editors like VS Code, without needing any build
>> steps and with end users being able to consume those source files
>> directly in any way they want (possibly also without build tools).
>> However, JSDoc can not currently do everything that regular TypeScript
>> syntax can do (there's some open issues regarding that in the
>> TypeScript repo).
>>
>> #!/JoePea
>>
>> On Wed, Oct 14, 2020 at 11:53 AM kai zhu  wrote:
>> >
>> > > Sorry but my question isn't about providing a tool to generate our 
>> > > documentations but to have a standard syntax to describe our code 
>> > > (signatures). ;)
>> >
>> > not standard-practice, but my style is to have documentation of functions 
>> > inside the function (rather than above it).
>> > simplifies doc-generation by calling function's `.toString()` (rather than 
>> > having to parse the parse the entire script):
>> >
>> > ```js
>> > let html;
>> > let local;
>> > local = {};
>> > local.foo1 = function (aa, bb) {
>> > /*
>> >  * this function will blah blah blah
>> >  */
>> > return aa + bb;
>> > };
>> > local.foo2 = function (cc, dd) {
>> > /*
>> >  * this function will yada yada yada
>> >  */
>> > return cc + dd;
>> > };
>> >
>> > // auto-generate doc for functions in namespace 
>> > html = "\n\n";
>> > Object.entries(local).sort().forEach(function ([
>> > name, obj
>> > ]) {
>> > if (typeof obj === "function") {
>> > obj.toString().replace((
>> > /function\b.*?(\([\S\s]*?\))\s*?\{\n?(\s*?\/\*[\S\s]*?\*\/)/
>> > ), function (ignore, signature, comment) {
>> > html += "function " + name + " " + signature.trim() + 
>> > "\n";
>> > html += "\n" + comment + "\n\n";
>> > html += "\n";
>> > });
>> > }
>> > });
>> > html += "\n";
>> > console.log(html);
>> > ```
>> >
>> > output
>> > ```html
>> > 
>> >
>> > function foo1 (aa, bb)
>> > 
>> > /*
>> >  * this function will blah blah blah
>> >  */
>> > 
>> >
>> > function foo2 (cc, dd)
>> > 
>> > /*
>> >  * this function will yada yada yada
>> >  */
>> > 
>> >
>> > 
>> > ```
>> >
>> >
>> > On Wed, Oct 14, 2020 at 5:25 AM Michaël Rouges  
>> > wrote:
>> >>
>> >> Sorry but my question isn't about providing a tool to generate our 
>> >> documentations but to have a standard syntax to describe our code 
>> >> (signatures). ;)
>> >>
>> >>
>> >> Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
>> >>
>> >>
>> >> Le mar. 13 oct. 2020 à 01:29, Jordan Harband  a écrit :
>> >>>
>> >>> Hopefully (imo) people are hand-writing more docs now, rather than 
>> >>> relying on autogenerated prose.
>> >>>
>> >>> On Mon, Oct 12, 2020 at 1:23 PM #!/JoePea  wrote:
>> >>>>
>> >>>

Re: Why does Object.keys return an Array instead of a Set?

2020-10-17 Thread #!/JoePea
Well that makes sense! Would it be worth adding an option like
`Object.keys(obj, true)` to return a set? Or perhaps
`Object.keySet(obj)`?
#!/JoePea

On Fri, Oct 16, 2020 at 11:54 PM Jordan Harband  wrote:
>
> Because Object.keys was standardized in 2009, 6 years before Set existed.
>
> On Fri, Oct 16, 2020 at 6:51 PM #!/JoePea  wrote:
>>
>> Sets are faster, even for tiny lists of four items. See the perf tests
>> (tested in Chrome):
>>
>> https://twitter.com/trusktr/status/1315848017535098880
>>
>> https://twitter.com/trusktr/status/1317281652540731392
>>
>> #!/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 ES6 modules in browsers going to get loaded level-by-level?

2020-10-16 Thread #!/JoePea
es-dev-server by open-wc seems to be import-aware.
https://open-wc.org/developing/es-dev-server.html
#!/JoePea

On Fri, Oct 16, 2020 at 6:40 PM #!/JoePea  wrote:
>
> So in practice, bundling is still a thing because there isn't an
> import-aware server that has been released that proves to be better
> than bundling? Or perhaps it's too much overhead to set up a server,
> so people just bundle?
>
> #!/JoePea
>
> On Wed, Oct 14, 2020 at 2:45 PM Randy Buchholz  wrote:
> >
> > I've been doing some work around module loading/importing recently, writing 
> > some "import awareness" into the server request pipeline. I'm also doing 
> > things on the client side, but I'm not set up to build a browser so I'm 
> > substituting a DI based `injection` approach for the `import` operation. 
> > It's given me a different perspective on module imports, especially when 
> > working with ES Classes. Here are my basic thoughts.
> >
> > To get to smarter imports both the client and server need  to be "import 
> > aware".  But I think just as importantly (and IMHO a prerequisite) is that 
> > the transport layer needs to directly support the concept of `import`. From 
> > the server side there is nothing in the message/request (e.g., in the 
> > header) that lets the server know the request is for an import - it just 
> > comes in as a Fetch. Knowing the type of request is an import up-front 
> > would allow early routing to "import handlers" on the server. I've 
> > suggested adding an `import` category to the headers  spec or extending 
> > `sec-fetch-dest` values to include `import` but there seems to be little 
> > interest.
> >
> > Also missing is a standard way to indicate what the client wants in the 
> > request. An `import` is basically a function call that uses "remote 
> > parameters" - the request response.
> > `{a, b, c} scoped = importFrom("/url");`
> > In worst-case form, the client is requesting a file and hoping it contains 
> > "parameters" usable by the import function. I say hoping, because the 
> > server doesn't know to return an importable file, it's up to the client to 
> > know what lies in the server url topology. Once the "importer" gets the 
> > parameter file there is another leap of faith (especially with named 
> > imports). Even if the file is importable, will it produce the correct 
> > types? We should be able to let the server know what we want. While this is 
> > too much info for a header, there should be a standard form of letting the 
> > server know what the client is looking for beyond "whatever is at this 
> > endpoint". Once a communication protocol is standardized, clients and 
> > servers can implement "import awareness".
> >
> > At least in my work, I've come to believe that the idea of "requesting a 
> > file to import" at a url address is too limiting. I really don't care where 
> > the items come from. Conceptually I'm thinking "give me these items" or 
> > "execute the import response process with these parameters", and not "give 
> > me this file". I almost see it as an HTTP verb -`IMPORT` lol. Anyway just 
> > my 2c.
> > ___
> > 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


Why does Object.keys return an Array instead of a Set?

2020-10-16 Thread #!/JoePea
Sets are faster, even for tiny lists of four items. See the perf tests
(tested in Chrome):

https://twitter.com/trusktr/status/1315848017535098880

https://twitter.com/trusktr/status/1317281652540731392

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-16 Thread #!/JoePea
So in practice, bundling is still a thing because there isn't an
import-aware server that has been released that proves to be better
than bundling? Or perhaps it's too much overhead to set up a server,
so people just bundle?

#!/JoePea

On Wed, Oct 14, 2020 at 2:45 PM Randy Buchholz  wrote:
>
> I've been doing some work around module loading/importing recently, writing 
> some "import awareness" into the server request pipeline. I'm also doing 
> things on the client side, but I'm not set up to build a browser so I'm 
> substituting a DI based `injection` approach for the `import` operation. It's 
> given me a different perspective on module imports, especially when working 
> with ES Classes. Here are my basic thoughts.
>
> To get to smarter imports both the client and server need  to be "import 
> aware".  But I think just as importantly (and IMHO a prerequisite) is that 
> the transport layer needs to directly support the concept of `import`. From 
> the server side there is nothing in the message/request (e.g., in the header) 
> that lets the server know the request is for an import - it just comes in as 
> a Fetch. Knowing the type of request is an import up-front would allow early 
> routing to "import handlers" on the server. I've suggested adding an `import` 
> category to the headers  spec or extending `sec-fetch-dest` values to include 
> `import` but there seems to be little interest.
>
> Also missing is a standard way to indicate what the client wants in the 
> request. An `import` is basically a function call that uses "remote 
> parameters" - the request response.
> `{a, b, c} scoped = importFrom("/url");`
> In worst-case form, the client is requesting a file and hoping it contains 
> "parameters" usable by the import function. I say hoping, because the server 
> doesn't know to return an importable file, it's up to the client to know what 
> lies in the server url topology. Once the "importer" gets the parameter file 
> there is another leap of faith (especially with named imports). Even if the 
> file is importable, will it produce the correct types? We should be able to 
> let the server know what we want. While this is too much info for a header, 
> there should be a standard form of letting the server know what the client is 
> looking for beyond "whatever is at this endpoint". Once a communication 
> protocol is standardized, clients and servers can implement "import 
> awareness".
>
> At least in my work, I've come to believe that the idea of "requesting a file 
> to import" at a url address is too limiting. I really don't care where the 
> items come from. Conceptually I'm thinking "give me these items" or "execute 
> the import response process with these parameters", and not "give me this 
> file". I almost see it as an HTTP verb -`IMPORT` lol. Anyway just my 2c.
> ___
> 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: Since JSDoc seems cerebrally dead...

2020-10-16 Thread #!/JoePea
Would official syntax be worth it (JSDoc being officially standardized)?

Maybe it's a matter of time: Perhaps now that JSDoc is useful for type
checking (thanks to TypeScript and its ability to type check plain
JavaScript that is annotated with JSDoc) it may be closer to reality.

I prefer JSDoc type annotation in plain .js files over writing .ts
files, because it means I can write type-checked code that has great
intellisense in modern editors like VS Code, without needing any build
steps and with end users being able to consume those source files
directly in any way they want (possibly also without build tools).
However, JSDoc can not currently do everything that regular TypeScript
syntax can do (there's some open issues regarding that in the
TypeScript repo).

#!/JoePea

On Wed, Oct 14, 2020 at 11:53 AM kai zhu  wrote:
>
> > Sorry but my question isn't about providing a tool to generate our 
> > documentations but to have a standard syntax to describe our code 
> > (signatures). ;)
>
> not standard-practice, but my style is to have documentation of functions 
> inside the function (rather than above it).
> simplifies doc-generation by calling function's `.toString()` (rather than 
> having to parse the parse the entire script):
>
> ```js
> let html;
> let local;
> local = {};
> local.foo1 = function (aa, bb) {
> /*
>  * this function will blah blah blah
>  */
> return aa + bb;
> };
> local.foo2 = function (cc, dd) {
> /*
>  * this function will yada yada yada
>  */
> return cc + dd;
> };
>
> // auto-generate doc for functions in namespace 
> html = "\n\n";
> Object.entries(local).sort().forEach(function ([
> name, obj
> ]) {
> if (typeof obj === "function") {
> obj.toString().replace((
> /function\b.*?(\([\S\s]*?\))\s*?\{\n?(\s*?\/\*[\S\s]*?\*\/)/
> ), function (ignore, signature, comment) {
> html += "function " + name + " " + signature.trim() + 
> "\n";
> html += "\n" + comment + "\n\n";
> html += "\n";
> });
> }
> });
> html += "\n";
> console.log(html);
> ```
>
> output
> ```html
> 
>
> function foo1 (aa, bb)
> 
> /*
>  * this function will blah blah blah
>  */
> 
>
> function foo2 (cc, dd)
> 
> /*
>  * this function will yada yada yada
>  */
> 
>
> 
> ```
>
>
> On Wed, Oct 14, 2020 at 5:25 AM Michaël Rouges  
> wrote:
>>
>> Sorry but my question isn't about providing a tool to generate our 
>> documentations but to have a standard syntax to describe our code 
>> (signatures). ;)
>>
>>
>> Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
>>
>>
>> Le mar. 13 oct. 2020 à 01:29, Jordan Harband  a écrit :
>>>
>>> Hopefully (imo) people are hand-writing more docs now, rather than relying 
>>> on autogenerated prose.
>>>
>>> On Mon, Oct 12, 2020 at 1:23 PM #!/JoePea  wrote:
>>>>
>>>> Why not? People are generating less docs now? That doesn't sound good!
>>>>
>>>> #!/JoePea
>>>>
>>>> On Mon, Aug 17, 2020 at 4:15 PM Isiah Meadows  
>>>> wrote:
>>>> >
>>>> > JSDoc is not dead (far from it), people just don't frequently use
>>>> > automated docs generation tooling in the JS community. Most the actual
>>>> > use JSDoc provides nowadays is editor autocomplete hints and
>>>> > integrating with TypeScript (in cases where changing the extension
>>>> > isn't possible for whatever reason), so while it's still useful, it's
>>>> > just not used in the same places it was used previously.
>>>> >
>>>> > -
>>>> >
>>>> > Isiah Meadows
>>>> > cont...@isiahmeadows.com
>>>> > www.isiahmeadows.com
>>>> >
>>>> > On Sun, Aug 16, 2020 at 6:39 PM Michaël Rouges 
>>>> >  wrote:
>>>> > >
>>>> > > Hi all,
>>>> > >
>>>> > > Since JSDoc seems cerebrally dead, why the TC39 doesn't make a real 
>>>> > > documentation standard, evolving with the langage?
>>>> > >
>>>> > > Actually, a part of  the JS community are exiling to TS to type 
>>>> > > anything and the rest are just despited by the very outdated version 
>>>> > > of JSDoc but don't want to add TS to their stack.
>>>> > >
>>>

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

2020-10-12 Thread #!/JoePea
Gotcha. So basically that tells the consumer "No, you can't use
Proxies". What I want to tell them is "Go ahead, use Proxies to your
heart's content", but I don't want to tell them to write all the
overly-complicated code required for their Proxies to work properly as
soon as I introduce a single private field within my class.


#!/JoePea

On Mon, Jul 27, 2020 at 3:33 PM Jordan Harband  wrote:
>
> oh oops, i meant `if (o !== this)` not `if (o.foo !== this)` :-)
>
> On Mon, Jul 27, 2020 at 3:06 PM #!/JoePea  wrote:
>>
>> > `o.foo(); // works`
>>
>> I think there is something missing from that example as that line
>> throws before it can get to the `new Proxy` line.
>>
>> #!/JoePea
>>
>> On Wed, Jul 15, 2020 at 10:47 PM Jordan Harband  wrote:
>> >
>> > So can:
>> > ```jsx
>> > const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
>> > o.foo(); // works
>> > new Proxy(o, {}).foo(); // throws
>> > ```
>> >
>> > (as would a class that used a closed-over WeakMap for each "private field")
>> >
>> > Private fields do not introduce any new hazards here.
>> >
>> > On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:
>> >>
>> >> >  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.
>> >> >>>>
>&g

Re: Private fields in sub-objects within class definition.

2020-10-12 Thread #!/JoePea
Sure, but I'm first curious about classes because in my example, the
code is all defined _inside_ a class definition's lexical scope, where
private fields (or keys) are _currently_ defined to exist, so it seems
like an approach we can currently take.

Private fields on objects without classes being in play would be neat too!

#!/JoePea

On Sun, Aug 9, 2020 at 7:55 PM Michael Theriot
 wrote:
>
> Why stop at class definitions?
>
> e.g.
> ```js
> let obj;
> {
>   let local = 0;
>   obj = {
> get local() {
>   return local;
> }
>   }
> }
> ```
>
> becomes
> ```js
> const obj = {
>   #local: 0,
>   get local() {
> return this.#local;
>   }
> }
> ```
>
> On Fri, Aug 7, 2020 at 3:33 PM #!/JoePea  wrote:
>>
>> Not sure if the following is exactly how we'd want it to be, but it
>> would be useful:
>>
>> ```js
>> class Foo {
>>   // calculatedValue is intended to have read-only properties
>>   calculatedValue = {
>> #x: 0,
>> get x() { return this.#x },
>> #y: 0,
>> get y() { return this.#y },
>> #z: 0,
>> get z() { return this.#z },
>>   }
>>
>>   update() {
>> this.calculatedValue.#x = 42 // ok
>> this.calculatedValue.#y = 42 // ok
>> this.calculatedValue.#z = 42 // ok
>>   }
>> }
>> ```
>>
>> End user:
>>
>> ```js
>> const foo = new Foo
>> foo.calculatedValue.x // ok
>> foo.calculatedValue.#x // syntax error
>> ```
>>
>> We could currently do something like this:
>>
>> ```js
>> class Foo {
>>   #calcX = 0
>>   #calcY = 0
>>   #calcZ = 0
>>
>>   // calculatedValue is intended to have read-only properties
>>   calculatedValue = (() => {
>> const self = this
>> return {
>>   get x() { return self.#calcX },
>>   get y() { return self.#calcY },
>>   get z() { return self.#calcZ },
>> }
>>   })()
>>
>>   update() {
>> this.#calcX = 42 // ok
>> this.#calcY = 42 // ok
>> this.#calcZ = 42 // ok
>>   }
>> }
>> ```
>>
>> Any plans for something like this? Is there a plan for private fields
>> for object literals? If so, maybe that can somehow tie into usage
>> within class bodies with WeakMap-ish semantics.
>>
>> #!/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: Since JSDoc seems cerebrally dead...

2020-10-12 Thread #!/JoePea
Why not? People are generating less docs now? That doesn't sound good!

#!/JoePea

On Mon, Aug 17, 2020 at 4:15 PM Isiah Meadows  wrote:
>
> JSDoc is not dead (far from it), people just don't frequently use
> automated docs generation tooling in the JS community. Most the actual
> use JSDoc provides nowadays is editor autocomplete hints and
> integrating with TypeScript (in cases where changing the extension
> isn't possible for whatever reason), so while it's still useful, it's
> just not used in the same places it was used previously.
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
>
> On Sun, Aug 16, 2020 at 6:39 PM Michaël Rouges  
> wrote:
> >
> > Hi all,
> >
> > Since JSDoc seems cerebrally dead, why the TC39 doesn't make a real 
> > documentation standard, evolving with the langage?
> >
> > Actually, a part of  the JS community are exiling to TS to type anything 
> > and the rest are just despited by the very outdated version of JSDoc but 
> > don't want to add TS to their stack.
> >
> > IMHO, it's really urgent to have something formal to solve that missing 
> > point of my favorite language.
> >
> > What would it take to make this dream come true, please?
> >
> >
> > Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
> > ___
> > 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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-12 Thread #!/JoePea
Right, exactly. So naively sending all dependencies wastefully is just
the first step.

> Afaik the more promising path are prefetch hints on the client. E.g. the
client (or initial HTML payload) knows the dependency tree, adds tags
for preloading the required modules, and then the browser can properly
handle fine-grained caching from there, only requesting what is actually
needed.

That may be nice, but I imagine people importing libraries from
different domains (without knowing the graphs, for example, in simple
codepen or jsfiddle demos with no build tooling).

So suppose the client code consists only of one single line of HTML, just

```html

Re: Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-12 Thread #!/JoePea
I'm asking about a server that, upon request of a `.js` file, knows
how to enumerate the dependency tree based on that file, _then_ HTTP
pushes all the modules at once.

So basically, from the code

```html

nested import statements

2020-10-12 Thread #!/JoePea
Why isn't it a thing yet?

- http://www.petecorey.com/blog/2016/07/17/meteors-nested-import-controversy/
- https://github.com/benjamn/reify/blob/master/WHY_NEST_IMPORTS.md

At runtime they'd be similar to `await`ing an `import` statement.

Maybe a requirement should be that nested (statically-analyzable)
imports should appear only within `async` functions (so they operate
the same as `await import()`).

Is there something bad about the idea that isn't described in those writings?

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Are ES6 modules in browsers going to get loaded level-by-level?

2020-10-10 Thread #!/JoePea
It's 5 years later, but still no (obvious) sign of HTTP/2 servers
specialized in ES Module push.

Do any exist? Anyone have a list? I'm especially interested in the
self-hostable servers, but also curious about solutions where we may
publish modules to.

The non-self-hosted solutions may be attractive to those people who
normally publish static sites and need to publish ES Modules as static
resources somewhere without the fuss if managing a server.

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A Function.tag proposal?

2020-09-24 Thread #!/JoePea
By the way, the VS Code plugin I use is [Comment tagged
templates](https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates).
Works great, allows any extension in the comment, and it will
highlight as long as you have that syntax installed separately.

I got tired of pasting my identity tag everywhere.

#!/JoePea

On Thu, Sep 24, 2020 at 2:25 PM #!/JoePea  wrote:
>
> I mean, it would be only a parse time cost if the identity tag is used like
>
> ```js
> String.tag`...anything...`
> ```
>
> assuming it is not monkey-patchable (readonly). But maybe if it is
> patchable then all bets are off, and it has a runtime cost.
>
> #!/JoePea
>
> On Thu, Sep 24, 2020 at 2:22 PM #!/JoePea  wrote:
> >
> > Perhaps a built-in identity tag would be only a parse-time performance cost.
> > #!/JoePea
> >
> > On Thu, Sep 24, 2020 at 2:21 PM #!/JoePea  wrote:
> > >
> > > I don't know what you mean about the raw stuff, but using `/*css*/`
> > > works perfectly fine in VS Code with a plugin. There's no reason
> > > intellisense can't work inside the commented string. If you meant
> > > about completing the `css` part, if you accidentally write `/*ccs*/`
> > > then the colors won't look right. Missing auto-completion inside the
> > > little comment isn't that bad.
> > >
> > > I prefer using the comment because using an identity tag just for
> > > syntax feels like I'm adding a performance cost for no reason related
> > > to my runtime code.
> > >
> > > But perhaps a built-in identity tag would be fast.
> > >
> > > #!/JoePea
> > >
> > > On Mon, Jun 22, 2020 at 11:02 AM Andrea Giammarchi
> > >  wrote:
> > > >
> > > > I think it doesn't matter where it lands, and I've overlooked at the 
> > > > already available String.raw.
> > > >
> > > > My idea is to have it "no matter where, or how named" as it's the 
> > > > functionality I am after, not the name.
> > > >
> > > > String.plain sounds great, but since template literals tag functions 
> > > > are named "template literals tag functions", I've thought String.tag 
> > > > would implicitly describe the intent.
> > > >
> > > > And then again, I don't care about the name, "we" (developers that use 
> > > > template literals a lot) would love it no matter how it's called ;-)
> > > >
> > > > On Mon, Jun 22, 2020 at 7:16 PM Bergi  wrote:
> > > >>
> > > >> Hi Andrea,
> > > >>
> > > >> my 5ct: Putting the static function on the `Function` object doesn't
> > > >> make any sense to me. Using `String.tag` seems like much more sensible
> > > >> choice. Or, how about `String.plain`, in contrast to `String.raw`?
> > > >>
> > > >> I can see the use case, altough I'd really prefer tooling to become 
> > > >> more
> > > >> intelligent in that regard.
> > > >>
> > > >> best,
> > > >>  Bergi
> > > >> ___
> > > >> 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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A Function.tag proposal?

2020-09-24 Thread #!/JoePea
I mean, it would be only a parse time cost if the identity tag is used like

```js
String.tag`...anything...`
```

assuming it is not monkey-patchable (readonly). But maybe if it is
patchable then all bets are off, and it has a runtime cost.

#!/JoePea

On Thu, Sep 24, 2020 at 2:22 PM #!/JoePea  wrote:
>
> Perhaps a built-in identity tag would be only a parse-time performance cost.
> #!/JoePea
>
> On Thu, Sep 24, 2020 at 2:21 PM #!/JoePea  wrote:
> >
> > I don't know what you mean about the raw stuff, but using `/*css*/`
> > works perfectly fine in VS Code with a plugin. There's no reason
> > intellisense can't work inside the commented string. If you meant
> > about completing the `css` part, if you accidentally write `/*ccs*/`
> > then the colors won't look right. Missing auto-completion inside the
> > little comment isn't that bad.
> >
> > I prefer using the comment because using an identity tag just for
> > syntax feels like I'm adding a performance cost for no reason related
> > to my runtime code.
> >
> > But perhaps a built-in identity tag would be fast.
> >
> > #!/JoePea
> >
> > On Mon, Jun 22, 2020 at 11:02 AM Andrea Giammarchi
> >  wrote:
> > >
> > > I think it doesn't matter where it lands, and I've overlooked at the 
> > > already available String.raw.
> > >
> > > My idea is to have it "no matter where, or how named" as it's the 
> > > functionality I am after, not the name.
> > >
> > > String.plain sounds great, but since template literals tag functions are 
> > > named "template literals tag functions", I've thought String.tag would 
> > > implicitly describe the intent.
> > >
> > > And then again, I don't care about the name, "we" (developers that use 
> > > template literals a lot) would love it no matter how it's called ;-)
> > >
> > > On Mon, Jun 22, 2020 at 7:16 PM Bergi  wrote:
> > >>
> > >> Hi Andrea,
> > >>
> > >> my 5ct: Putting the static function on the `Function` object doesn't
> > >> make any sense to me. Using `String.tag` seems like much more sensible
> > >> choice. Or, how about `String.plain`, in contrast to `String.raw`?
> > >>
> > >> I can see the use case, altough I'd really prefer tooling to become more
> > >> intelligent in that regard.
> > >>
> > >> best,
> > >>  Bergi
> > >> ___
> > >> 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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A Function.tag proposal?

2020-09-24 Thread #!/JoePea
Perhaps a built-in identity tag would be only a parse-time performance cost.
#!/JoePea

On Thu, Sep 24, 2020 at 2:21 PM #!/JoePea  wrote:
>
> I don't know what you mean about the raw stuff, but using `/*css*/`
> works perfectly fine in VS Code with a plugin. There's no reason
> intellisense can't work inside the commented string. If you meant
> about completing the `css` part, if you accidentally write `/*ccs*/`
> then the colors won't look right. Missing auto-completion inside the
> little comment isn't that bad.
>
> I prefer using the comment because using an identity tag just for
> syntax feels like I'm adding a performance cost for no reason related
> to my runtime code.
>
> But perhaps a built-in identity tag would be fast.
>
> #!/JoePea
>
> On Mon, Jun 22, 2020 at 11:02 AM Andrea Giammarchi
>  wrote:
> >
> > I think it doesn't matter where it lands, and I've overlooked at the 
> > already available String.raw.
> >
> > My idea is to have it "no matter where, or how named" as it's the 
> > functionality I am after, not the name.
> >
> > String.plain sounds great, but since template literals tag functions are 
> > named "template literals tag functions", I've thought String.tag would 
> > implicitly describe the intent.
> >
> > And then again, I don't care about the name, "we" (developers that use 
> > template literals a lot) would love it no matter how it's called ;-)
> >
> > On Mon, Jun 22, 2020 at 7:16 PM Bergi  wrote:
> >>
> >> Hi Andrea,
> >>
> >> my 5ct: Putting the static function on the `Function` object doesn't
> >> make any sense to me. Using `String.tag` seems like much more sensible
> >> choice. Or, how about `String.plain`, in contrast to `String.raw`?
> >>
> >> I can see the use case, altough I'd really prefer tooling to become more
> >> intelligent in that regard.
> >>
> >> best,
> >>  Bergi
> >> ___
> >> 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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A Function.tag proposal?

2020-09-24 Thread #!/JoePea
I don't know what you mean about the raw stuff, but using `/*css*/`
works perfectly fine in VS Code with a plugin. There's no reason
intellisense can't work inside the commented string. If you meant
about completing the `css` part, if you accidentally write `/*ccs*/`
then the colors won't look right. Missing auto-completion inside the
little comment isn't that bad.

I prefer using the comment because using an identity tag just for
syntax feels like I'm adding a performance cost for no reason related
to my runtime code.

But perhaps a built-in identity tag would be fast.

#!/JoePea

On Mon, Jun 22, 2020 at 11:02 AM Andrea Giammarchi
 wrote:
>
> I think it doesn't matter where it lands, and I've overlooked at the already 
> available String.raw.
>
> My idea is to have it "no matter where, or how named" as it's the 
> functionality I am after, not the name.
>
> String.plain sounds great, but since template literals tag functions are 
> named "template literals tag functions", I've thought String.tag would 
> implicitly describe the intent.
>
> And then again, I don't care about the name, "we" (developers that use 
> template literals a lot) would love it no matter how it's called ;-)
>
> On Mon, Jun 22, 2020 at 7:16 PM Bergi  wrote:
>>
>> Hi Andrea,
>>
>> my 5ct: Putting the static function on the `Function` object doesn't
>> make any sense to me. Using `String.tag` seems like much more sensible
>> choice. Or, how about `String.plain`, in contrast to `String.raw`?
>>
>> I can see the use case, altough I'd really prefer tooling to become more
>> intelligent in that regard.
>>
>> best,
>>  Bergi
>> ___
>> 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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Private fields in sub-objects within class definition.

2020-08-07 Thread #!/JoePea
Not sure if the following is exactly how we'd want it to be, but it
would be useful:

```js
class Foo {
  // calculatedValue is intended to have read-only properties
  calculatedValue = {
#x: 0,
get x() { return this.#x },
#y: 0,
get y() { return this.#y },
#z: 0,
get z() { return this.#z },
  }

  update() {
this.calculatedValue.#x = 42 // ok
this.calculatedValue.#y = 42 // ok
this.calculatedValue.#z = 42 // ok
  }
}
```

End user:

```js
const foo = new Foo
foo.calculatedValue.x // ok
foo.calculatedValue.#x // syntax error
```

We could currently do something like this:

```js
class Foo {
  #calcX = 0
  #calcY = 0
  #calcZ = 0

  // calculatedValue is intended to have read-only properties
  calculatedValue = (() => {
const self = this
return {
  get x() { return self.#calcX },
  get y() { return self.#calcY },
  get z() { return self.#calcZ },
}
  })()

  update() {
this.#calcX = 42 // ok
this.#calcY = 42 // ok
this.#calcZ = 42 // ok
  }
}
```

Any plans for something like this? Is there a plan for private fields
for object literals? If so, maybe that can somehow tie into usage
within class bodies with WeakMap-ish semantics.

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2020-07-27 Thread #!/JoePea
> `o.foo(); // works`

I think there is something missing from that example as that line
throws before it can get to the `new Proxy` line.

#!/JoePea

On Wed, Jul 15, 2020 at 10:47 PM Jordan Harband  wrote:
>
> So can:
> ```jsx
> const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
> o.foo(); // works
> new Proxy(o, {}).foo(); // throws
> ```
>
> (as would a class that used a closed-over WeakMap for each "private field")
>
> Private fields do not introduce any new hazards here.
>
> On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:
>>
>> >  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() {
>> >>>>>
>> &g

Re: Why aren't interpolation values in tagged template calls saved as a cached array?

2020-07-27 Thread #!/JoePea
> to start with, assuming the same `arguments` object is passed twice to two 
> different invokes of a callback, would break down to ES3 and lower.

I know, that's what I mentioned (it is historical, will never be the
same object). :)

> interpolated values you are passing around are always different, so I can't 
> understand why would you expect an always same Array in there

That's true. However, making a new array each time causes garbage
collection that can otherwise be avoided.

The interpolation values array could be made immutable for the user,
while only the engine could be allowed to modify the content. The
length of the array will never change. This will be much better than
making a new array every time.

Imagine, for example, hundreds of templates being called repeatedly
for animations. It would simply be better if the values (f.e. numbers)
were the only things changing. People could of course pass new objects
as values on each update, but then that's their problem and an
experienced developer will know about the cost in that case.

> none of these suggestions would improve anything in the wild

You don't think this idea would help for performance in some way?

#!/JoePea

On Sun, Jul 26, 2020 at 11:33 AM Andrea Giammarchi
 wrote:
>
> there is some fundamental misconception of the ECMAScript standard in these 
> examples ... to start with, assuming the same `arguments` object is passed 
> twice to two different invokes of a callback, would break down to ES3 and 
> lower.
>
> Secondly, interpolated values you are passing around are always different, so 
> I can't understand why would you expect an always same Array in there ... 
> it's not the same as the template one, which is immutable, aka frozen, and it 
> can carry any different value at any different position.
>
> Accordingly, the current standard for template literals tags function is 
> nearly perfect, and none of these suggestions would improve anything in the 
> wild (using template literals since 2015, I think I've consumed them all in 
> all flavours).
>
> Regards.
>
> On Sun, Jul 26, 2020 at 8:08 PM #!/JoePea  wrote:
>>
>> The following doesn't work either, and obviously it probably will
>> never change because it is historical:
>>
>> ```js
>> argsArrays = []
>>
>> function html() {
>> argsArrays.push(arguments)
>> }
>>
>> let n = 0
>> let n2 = 0
>>
>> function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>>
>> render()
>> render()
>>
>> console.log(argsArrays[0] === argsArrays[1]) // false!
>> ```
>>
>> So yeah, just wondering why our only option is to use `...args` and
>> create new arrays each time, thus the performance is not optimized
>> like it is with the string parts.
>>
>> #!/JoePea
>>
>> On Sun, Jul 26, 2020 at 10:49 AM #!/JoePea  wrote:
>> >
>> > What I mean is,
>> >
>> > We can currently do this (try it in console):
>> >
>> > ```js
>> > arrays = []
>> >
>> > function html(parts) { arrays.push(parts) }
>> >
>> > let n = 0
>> > let n2 = 0
>> >
>> > function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>> >
>> > render()
>> > render()
>> >
>> > console.log(arrays[0] === arrays[1]) // true! <--- This!
>> > ```
>> >
>> > But why don't specs allows us to do the following as well? (don't run
>> > it, it doesn't work as intended)
>> >
>> > ```js
>> > partsArrays = []
>> > valuesArrays = []
>> >
>> > function html(parts, values) {
>> > partsArrays.push(parts)
>> > valuesArrays.push(values)
>> > }
>> >
>> > let n = 0
>> > let n2 = 0
>> >
>> > function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>> >
>> > render()
>> > render()
>> >
>> > console.log(partsArrays[0] === partsArrays[1]) // true!
>> > console.log(valuesArrays[0] === valuesArrays[1]) // This would be
>> > convenient too! I think?
>> > ```
>> >
>> > Instead, if we want an array of the values, we have to use `arguments`
>> > or `...args`. For example:
>> >
>> > ```js
>> > // ... same ...
>> > function html(parts, ...values) {
>> > partsArrays.push(parts)
>> > valuesArrays.push(values)
>> > }
>> > // ... same ...
>> > console.log(partsArrays[0] === partsArrays[1]) // true!
>> > console.log(valuesArrays[0] === valuesArrays[1]) // false! New array every 
>> > time.
>> > ```
>> >
>> > Seems like it would've been great to have the cached values arrays
>> > too. Why isn't this the case?
>> >
>> > #!/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: Why aren't interpolation values in tagged template calls saved as a cached array?

2020-07-26 Thread #!/JoePea
The following doesn't work either, and obviously it probably will
never change because it is historical:

```js
argsArrays = []

function html() {
argsArrays.push(arguments)
}

let n = 0
let n2 = 0

function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }

render()
render()

console.log(argsArrays[0] === argsArrays[1]) // false!
```

So yeah, just wondering why our only option is to use `...args` and
create new arrays each time, thus the performance is not optimized
like it is with the string parts.

#!/JoePea

On Sun, Jul 26, 2020 at 10:49 AM #!/JoePea  wrote:
>
> What I mean is,
>
> We can currently do this (try it in console):
>
> ```js
> arrays = []
>
> function html(parts) { arrays.push(parts) }
>
> let n = 0
> let n2 = 0
>
> function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>
> render()
> render()
>
> console.log(arrays[0] === arrays[1]) // true! <--- This!
> ```
>
> But why don't specs allows us to do the following as well? (don't run
> it, it doesn't work as intended)
>
> ```js
> partsArrays = []
> valuesArrays = []
>
> function html(parts, values) {
> partsArrays.push(parts)
> valuesArrays.push(values)
> }
>
> let n = 0
> let n2 = 0
>
> function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>
> render()
> render()
>
> console.log(partsArrays[0] === partsArrays[1]) // true!
> console.log(valuesArrays[0] === valuesArrays[1]) // This would be
> convenient too! I think?
> ```
>
> Instead, if we want an array of the values, we have to use `arguments`
> or `...args`. For example:
>
> ```js
> // ... same ...
> function html(parts, ...values) {
> partsArrays.push(parts)
> valuesArrays.push(values)
> }
> // ... same ...
> console.log(partsArrays[0] === partsArrays[1]) // true!
> console.log(valuesArrays[0] === valuesArrays[1]) // false! New array every 
> time.
> ```
>
> Seems like it would've been great to have the cached values arrays
> too. Why isn't this the case?
>
> #!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Why aren't interpolation values in tagged template calls saved as a cached array?

2020-07-26 Thread #!/JoePea
What I mean is,

We can currently do this (try it in console):

```js
arrays = []

function html(parts) { arrays.push(parts) }

let n = 0
let n2 = 0

function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }

render()
render()

console.log(arrays[0] === arrays[1]) // true! <--- This!
```

But why don't specs allows us to do the following as well? (don't run
it, it doesn't work as intended)

```js
partsArrays = []
valuesArrays = []

function html(parts, values) {
partsArrays.push(parts)
valuesArrays.push(values)
}

let n = 0
let n2 = 0

function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }

render()
render()

console.log(partsArrays[0] === partsArrays[1]) // true!
console.log(valuesArrays[0] === valuesArrays[1]) // This would be
convenient too! I think?
```

Instead, if we want an array of the values, we have to use `arguments`
or `...args`. For example:

```js
// ... same ...
function html(parts, ...values) {
partsArrays.push(parts)
valuesArrays.push(values)
}
// ... same ...
console.log(partsArrays[0] === partsArrays[1]) // true!
console.log(valuesArrays[0] === valuesArrays[1]) // false! New array every time.
```

Seems like it would've been great to have the cached values arrays
too. Why isn't this the case?

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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&quot</a>;>
>> > 
>> > (async function foo() {
>> > "use strict";
>> > let thirdParty = window.HTTPClient;
>> > let myFetch = thirdParty.createFetch(
>> > thirdParty.base("<a  rel="nofollow" href="https://api.stripe.com/v1&quot">https://api.stripe.com/v1&quot</a>;),
>> > thirdParty.accept(&q

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.
>>>>>
>>>>&g

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 

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

2020-07-10 Thread #!/JoePea
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&quot</a>;>
> 
> (async function foo() {
> "use strict";
> let thirdParty = window.HTTPClient;
> let myFetch = thirdParty.createFetch(
> thirdParty.base("<a  rel="nofollow" href="https://api.stripe.com/v1&quot">https://api.stripe.com/v1&quot</a>;),
> thirdParty.accept("application/json")
> );
> let response = await myFetch("/customers/5");
> console.log(response.jsonData);
> /*
> dev-console-output - <a  rel="nofollow" href="http://localhost:8081/test.html?modeDebugFetch=1">http://localhost:8081/test.html?modeDebugFetch=1</a>
> fetch-call-arguments:
> [
> "<a  rel="nofollow" href="https://api.stripe.com/v1/customers/5&quot">https://api.stripe.com/v1/customers/5&quot</a>;,
> {
> "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 (test.html?modeDebugFetch=1:35)
> at test.html?modeDebugFetch=1:64
> */
> }());
> 
> 
> ```
>
>
> 2. here's real-world-hack added to npm-cli.js to debug its http-requests
>
> ```diff
> C:\Program Files\nodejs\node_modules\npm>git diff
> diff --git a/bin/npm-cli.js b/bin/npm-cli.js
> index 561dec0..98cafb8 100644
> --- a/bin/npm-cli.js
> +++ b/bin/npm-cli.js
> @@ -2,17 +2,6 @@
>  ;(function () { // wrapper in case we're in module_context mode
> +// hack - debug http-request
> +let httpRequest;
> +httpRequest = require("https").request.bind(require("https"));
> +require("https").request = function (...argList) {
> +if (process.env.NPM_DEBUG) {
> +console.error(
> +"npm - httpRequest - " + JSON.stringify(argList.slice(0, 2), 
> undefined, 4)
> +);
> +}
> +return httpRequest(...argList);
> +};
>// windows: running "npm blah" in this folder will invoke WSH, not node.
>
> C:\Program Files\nodejs\node_modules\npm>
> ```
>
> ```mingw-bash
> $ NPM_DEBUG=1 npm publish foo
> # console-ouput:
> # npm - http

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

2020-07-10 Thread #!/JoePea
Thanks for the idea! That's similar to what I thought would be necessary. I
was hoping to monkey patch `fetch()` to have it get the trace if any
`fetch` call, but they would not be async stack traces. For async traces it
would require instrumentation by injecting code similar to yours (I want to
detect traces in third-party code installed locally).

#!/JoePea

On Wed, Jul 8, 2020, 2:13 AM kai zhu  wrote:

> here's a simple throwaway-function you can wrap around promises like fetch
> to get the caller's async-stack-trace `promiseWithErrorStack`:
>
> ```html
> 
> 
> 
> test.html
> 
> (async function foo() {
> function promiseWithErrorStack(promise) {
> /*
>  * this function will append current-stack to any err caught from
> <promise>
>  */
> let errStack;
> errStack = new Error().stack;
> return new Promise(function (resolve, reject) {
> promise.then(resolve).catch(function (err) {
> // append current errStack to err.stack
> if (err && typeof err.stack === "string") {
> err.stack += "\n" + errStack;
> }
> reject(err);
> });
> });
> }
> await promiseWithErrorStack(fetch("<a  rel="nofollow" href="https://example.com&quot">https://example.com&quot</a>;)); // at foo
> (test.html:23)
>
> /*
> console-output:
>
> Uncaught (in promise) TypeError: Failed to fetch
> Error
> at promiseWithErrorStack (test.html:12)
> at foo (test.html:23) // async-stack-trace
> at test.html:32
> */
> }());
> 
> 
> ```
>
> On Tue, Jul 7, 2020 at 11:54 PM #!/JoePea  wrote:
>
>> Is there some way (perhaps by patching methods on objects?) so we can
>> track async call stacks?
>>
>> When we pause code in devtools, we are able to see the async stack
>> trace of the code.
>>
>> What I'd like to do is to effectively detect the same thing as
>> devtools does at some point in any code. As a specific example, I'd
>> like to detect the async stack trace of any call to `fetch`.
>>
>> Is such a thing possible with runtime code?
>>
>> Or would it require instrumentation of the source code?
>>
>> #!/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


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

2020-07-07 Thread #!/JoePea
Is there some way (perhaps by patching methods on objects?) so we can
track async call stacks?

When we pause code in devtools, we are able to see the async stack
trace of the code.

What I'd like to do is to effectively detect the same thing as
devtools does at some point in any code. As a specific example, I'd
like to detect the async stack trace of any call to `fetch`.

Is such a thing possible with runtime code?

Or would it require instrumentation of the source code?

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2020-06-30 Thread #!/JoePea
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


A way to construct Functions with custom scopes?

2020-06-10 Thread #!/JoePea
For example, what if we could write something like

```js
function foo() {
  var x = 10
}

const [scope, returnValue] = scope from foo()

// can't do anything with `scope` directly, it's like an empty object
(an exotic object?).
console.log(getOwnAndInheritedKeys(scope)) // empty array

new Function('console.log(x)', { scope }) // logs 10
```

Or something.

Maybe we can pass objects, and the keys are used for scope, similar to
`with`, but they are passed by reference into the scope:

```js
new Function('console.log(x)', { scope: { x: 10 } }) // logs 10
```

I think this would open up the doors to frameworks that want to create
expressions in things like Element attributes, to make it easy for
those expression to have access to certain variables. Currently it is
difficult to make this happen; the cleanest ways of doing it involve
build steps. With this idea we would not need build steps to have a
clean way of doing it.

#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2020-04-30 Thread #!/JoePea
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


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

2020-04-30 Thread #!/JoePea
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


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-11-22 Thread #!/JoePea
> Then why was you previous mail saying that browsers should fix it?

Because I believe they should, but I know they won't. :)

> It means "that thing that `this` would return in global scope".  No more,
no less.

And (maybe unfortunately) for many people that amounts to being equivalent
to "window". (I know it is wrong, but that's what many people think while
not knowing about window proxies).

On Thu, Nov 21, 2019 at 2:37 PM Boris Zbarsky  wrote:

> On 11/21/19 5:21 PM, #!/JoePea wrote:
> >> They were duly marked invalid, because the problem was with the
> expectations, not the behavior...
> >
> > It's a design bug.
>
> Well, sure, if we're talking about the fact that there is no clear
> separation in the web platform's exposed objects between "a container
> that can be navigated" and "the thing currently loaded in that
> container"; both are represented, kinda weirdly, by "window".
>
> > I know, impossible to fix.
>
> Then why was you previous mail saying that browsers should fix it?
>
> > I'm not sure I even know what "globalThis" means now. :)
>
> It means "that thing that `this` would return in global scope".  No
> more, no less.
>
> In practice, in web pages, that thing is a WindowProxy object as defined
> at
>
> https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object
>
> -Boris
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Proxy handler.has() does not have a receiver argument?

2019-11-22 Thread #!/JoePea
I forgot to add, this even works with builtin scenarios like Custom
Elements,

```js
class MyEl extends mix(HTMLButtonElement, One, Two, Three) { /* ... */ }
customElements.define('my-el', MyEl)
```

On Fri, Nov 22, 2019 at 9:36 AM #!/JoePea  wrote:

> HI Cyril, thanks for pointing that out! I know about those, I've been
> using class-factory mixins for a while now. But the problem with them is
> having to wrap all your classes in a function, which gets much more painful
> in TypeScript with all the type-annotation boilerplate that is required.
>
> For example, here's a boilerplate-heavy mixin of mine:
>
> - Header:
> https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L55
> - Footer:
> https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L615
> - Mixin helper application (provides mixin result caching, deduplication,
> Symbol.hasInstance, etc):
> https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L662
> - The type system that I imported from my lowclass lib:
> https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L2
>
> Multiple inheritance with Proxies actually turns out very easy to type in
> TypeScript, and a lot more convenient than class factories. So, given a set
> of regular classes,
>
> ```js
> class One {
>   doOne() { /* ... */ }
> }
>
> class Two {
>   doTwo() { /* ... */ }
> }
>
> class Three {
>   doThree() { /* ... */ }
> }
> ```
>
> a Proxy-based multiple inheritance system makes the composition super
> easy, clean, and simple. We can convert the previous example into:
>
> ```js
> import mix from './mix'
>
> class One {
>   doOne() { /* ... */ }
> }
>
> class Two {
>   doTwo() { /* ... */ }
> }
>
> class Three extends mix(One, Two) {
>   doThree() { /* ... */ }
>   doAll() {
> this.doOne()
> this.doTwo()
> this.doThree()
>   }
> }
> ```
>
> All without touching the original source of the `One` and `Two` classes.
> How convenient, and easier to read and look at!
>
> My particular implementation will allow to call individual constructors
> with specific args, unlike the class-factory mixins. For example,
>
> ```js
> import mix from './mix'
>
> class One {
>   constructor(arg1, arg2) {/*...*/}
>   doOne() { /* ... */ }
> }
>
> class Two {
>   constructor(arg3) {/*...*/}
>   doTwo() { /* ... */ }
> }
>
> class Three extends mix(One, Two) {
>   constructor(arg1, arg2, arg3) {
> this.callConstructor(One, arg1, arg2)
> this.callConstructor(Two, arg3)
>   }
>   doThree() { /* ... */ }
>   doAll() {
> this.doOne()
> this.doTwo()
> this.doThree()
>   }
> }
> ```
>
> At the moment I'm looking to convert from my Proxies-on-prototypes
> implementation to Proxies-on-instances so that things like `in` operator
> will work, and implementation will be simpler and easier. Otherwise if the
> `has` trap had a `receiver` parameter, then I could stick with the
> Proxies-on-prototypes version which would be more efficient (the Proxy
> would be re-used on the prototype chain instead of being created once per
> instance).
>
> Would it be worth adding a `receiver` parameter to the `has` trap in the
> specs? Seems like it would be totally backwards compatible, because current
> code that doesn't rely on it could continue not relying on it oblivious to
> the new parameter.
>
> All the best,
> - Joe
>
> On Fri, Nov 22, 2019 at 3:55 AM Cyril Auburtin 
> wrote:
>
>> It's not answering your issue with Proxy but more about multiple
>> inheritance
>>
>> It can be solved in a static way:
>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Mix-ins
>>
>> Concrete example here:
>> https://github.com/pepabo/gmopg/blob/master/src/gmopg.ts#L10
>>
>> On Fri, Nov 22, 2019 at 4:23 AM #!/JoePea  wrote:
>>
>>> After messing with Proxy-on-prototypes for two days, I've just come to
>>> the conclusion that I probably need to have Proxies on this (the
>>> receiver) returned from constructors to achieve what I want. At least,
>>> it's much easier to code it that way. I think it'd be nice to have
>>> receiver on all inheritance-related traps. That might make some things
>>> easier.
>>>
>>> On Thu, Nov 21, 2019 at 2:55 PM #!/JoePea  wrote:
>>> >
>>> > I really thing that because `has` is about detecting inherited
>>> > properties, the `receiver` parameter should be included. For things
>>> > like `ownKeys`, which are not about inheritance, then yeah, let's not
>>> &

Re: Re: Proxy handler.has() does not have a receiver argument?

2019-11-22 Thread #!/JoePea
HI Cyril, thanks for pointing that out! I know about those, I've been using
class-factory mixins for a while now. But the problem with them is having
to wrap all your classes in a function, which gets much more painful in
TypeScript with all the type-annotation boilerplate that is required.

For example, here's a boilerplate-heavy mixin of mine:

- Header:
https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L55
- Footer:
https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L615
- Mixin helper application (provides mixin result caching, deduplication,
Symbol.hasInstance, etc):
https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L662
- The type system that I imported from my lowclass lib:
https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L2

Multiple inheritance with Proxies actually turns out very easy to type in
TypeScript, and a lot more convenient than class factories. So, given a set
of regular classes,

```js
class One {
  doOne() { /* ... */ }
}

class Two {
  doTwo() { /* ... */ }
}

class Three {
  doThree() { /* ... */ }
}
```

a Proxy-based multiple inheritance system makes the composition super easy,
clean, and simple. We can convert the previous example into:

```js
import mix from './mix'

class One {
  doOne() { /* ... */ }
}

class Two {
  doTwo() { /* ... */ }
}

class Three extends mix(One, Two) {
  doThree() { /* ... */ }
  doAll() {
this.doOne()
this.doTwo()
this.doThree()
  }
}
```

All without touching the original source of the `One` and `Two` classes.
How convenient, and easier to read and look at!

My particular implementation will allow to call individual constructors
with specific args, unlike the class-factory mixins. For example,

```js
import mix from './mix'

class One {
  constructor(arg1, arg2) {/*...*/}
  doOne() { /* ... */ }
}

class Two {
  constructor(arg3) {/*...*/}
  doTwo() { /* ... */ }
}

class Three extends mix(One, Two) {
  constructor(arg1, arg2, arg3) {
this.callConstructor(One, arg1, arg2)
this.callConstructor(Two, arg3)
  }
  doThree() { /* ... */ }
  doAll() {
this.doOne()
this.doTwo()
this.doThree()
  }
}
```

At the moment I'm looking to convert from my Proxies-on-prototypes
implementation to Proxies-on-instances so that things like `in` operator
will work, and implementation will be simpler and easier. Otherwise if the
`has` trap had a `receiver` parameter, then I could stick with the
Proxies-on-prototypes version which would be more efficient (the Proxy
would be re-used on the prototype chain instead of being created once per
instance).

Would it be worth adding a `receiver` parameter to the `has` trap in the
specs? Seems like it would be totally backwards compatible, because current
code that doesn't rely on it could continue not relying on it oblivious to
the new parameter.

All the best,
- Joe

On Fri, Nov 22, 2019 at 3:55 AM Cyril Auburtin 
wrote:

> It's not answering your issue with Proxy but more about multiple
> inheritance
>
> It can be solved in a static way:
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Mix-ins
>
> Concrete example here:
> https://github.com/pepabo/gmopg/blob/master/src/gmopg.ts#L10
>
> On Fri, Nov 22, 2019 at 4:23 AM #!/JoePea  wrote:
>
>> After messing with Proxy-on-prototypes for two days, I've just come to
>> the conclusion that I probably need to have Proxies on this (the
>> receiver) returned from constructors to achieve what I want. At least,
>> it's much easier to code it that way. I think it'd be nice to have
>> receiver on all inheritance-related traps. That might make some things
>> easier.
>>
>> On Thu, Nov 21, 2019 at 2:55 PM #!/JoePea  wrote:
>> >
>> > I really thing that because `has` is about detecting inherited
>> > properties, the `receiver` parameter should be included. For things
>> > like `ownKeys`, which are not about inheritance, then yeah, let's not
>> > add receiver there.
>> >
>> > I'm trying to implement my own multiple inheritance, but now I
>> > stumbled on how to make it send back true for inherited keys when I
>> > need to fork the lookup based on instances that are `WeakMap`ed to the
>> > `receiver`.
>> ___
>> 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: Re: Proxy handler.has() does not have a receiver argument?

2019-11-21 Thread #!/JoePea
After messing with Proxy-on-prototypes for two days, I've just come to
the conclusion that I probably need to have Proxies on this (the
receiver) returned from constructors to achieve what I want. At least,
it's much easier to code it that way. I think it'd be nice to have
receiver on all inheritance-related traps. That might make some things
easier.

On Thu, Nov 21, 2019 at 2:55 PM #!/JoePea  wrote:
>
> I really thing that because `has` is about detecting inherited
> properties, the `receiver` parameter should be included. For things
> like `ownKeys`, which are not about inheritance, then yeah, let's not
> add receiver there.
>
> I'm trying to implement my own multiple inheritance, but now I
> stumbled on how to make it send back true for inherited keys when I
> need to fork the lookup based on instances that are `WeakMap`ed to the
> `receiver`.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy Reflect.has() call causes infinite recursion? (#!/JoePea)

2019-11-21 Thread #!/JoePea
Any idea why it isn't spamming the console? I mean, if it is
recursive, shouldn't it fire my console.logs over and over, like
50,000 times, before finally throwing the error?

On Thu, Nov 21, 2019 at 3:12 PM Alex Vincent  wrote:
>
> I'm afraid your testcase is still far too complicated to really figure out at 
> first glance.  It looks like you're trying to implement a mixin pattern.
>
> In my experience, it's better to implement the getPrototypeOf, 
> getOwnPropertyDescriptor, and defineProperty traps, and maybe make your get, 
> set, and has traps depend on them.
>
> Yes, that means you have to read the ECMAScript specification, section 9.5 
> carefully.  Yes, it's a major pain point.  I can only point you to my own 
> efforts in es-membrane to implement the specified traps.
>
> https://github.com/ajvincent/es-membrane/blob/master/source/ObjectGraphHandler.js
> ___
> 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: Re: Proxy handler.has() does not have a receiver argument?

2019-11-21 Thread #!/JoePea
I really thing that because `has` is about detecting inherited
properties, the `receiver` parameter should be included. For things
like `ownKeys`, which are not about inheritance, then yeah, let's not
add receiver there.

I'm trying to implement my own multiple inheritance, but now I
stumbled on how to make it send back true for inherited keys when I
need to fork the lookup based on instances that are `WeakMap`ed to the
`receiver`.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-11-21 Thread #!/JoePea
I should stop asking questions about something that is highly-unlikely
to change! I can live with it. :) Thanks anyways for the insights. -
Joe

On Thu, Nov 21, 2019 at 2:21 PM #!/JoePea  wrote:
>
> > They were duly marked invalid, because the problem was with the 
> > expectations, not the behavior...
>
> It's a design bug. I know, impossible to fix. I consider such things
> valid bugs, even if no action can be taken on them.
>
> > because reality does not match what they had been told
>
> Reality didn't match what was intuitive. I'd say it is a DX flaw.
>
> Honestly though, I don't know what a fix would be.
>
> I'm not sure I even know what "globalThis" means now. :)
>
>
> On Sun, Nov 17, 2019 at 11:52 AM Boris Zbarsky  wrote:
> >
> > On 11/16/19 12:52 PM, #!/JoePea wrote:
> > > That's the thing: the only people that may get confused are Ecmascript
> > > and JS-Engine experts who know the internals very intimately.
> >
> > No, it's just people who have functions return values they do not expect.
> >
> > > and for those people that could possibly get confused, it would be
> > > because they are familiar with browser internals (or hit a browser
> > > *bug* like you describe)
> >
> > No, you misunderstand.  The bug reports were filed because the behavior
> > was not what people expected.  They were duly marked invalid, because
> > the problem was with the expectations, not the behavior...
> >
> > > For all intents and purpose, every developer I've talked to, and every
> > > article I've read, treats things like `window` as the global object.
> >
> > And this is mostly fine as long as you don't call functions from
> > navigated-away-from windows. Which most people don't, most of the time.
> > And when they do, they get _very_ confused by the results, because
> > reality does not match what they had been told.
> >
> > But that doesn't mean we should double down on telling them things that
> > don't match reality.
> >
> > > I strongly believe that things should be made intuitive for the vast
> > > majority of users
> >
> > I agree, but in this specific context, what does that mean in terms of
> > concrete proposals you are making?
> >
> > -Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-11-21 Thread #!/JoePea
> They were duly marked invalid, because the problem was with the expectations, 
> not the behavior...

It's a design bug. I know, impossible to fix. I consider such things
valid bugs, even if no action can be taken on them.

> because reality does not match what they had been told

Reality didn't match what was intuitive. I'd say it is a DX flaw.

Honestly though, I don't know what a fix would be.

I'm not sure I even know what "globalThis" means now. :)


On Sun, Nov 17, 2019 at 11:52 AM Boris Zbarsky  wrote:
>
> On 11/16/19 12:52 PM, #!/JoePea wrote:
> > That's the thing: the only people that may get confused are Ecmascript
> > and JS-Engine experts who know the internals very intimately.
>
> No, it's just people who have functions return values they do not expect.
>
> > and for those people that could possibly get confused, it would be
> > because they are familiar with browser internals (or hit a browser
> > *bug* like you describe)
>
> No, you misunderstand.  The bug reports were filed because the behavior
> was not what people expected.  They were duly marked invalid, because
> the problem was with the expectations, not the behavior...
>
> > For all intents and purpose, every developer I've talked to, and every
> > article I've read, treats things like `window` as the global object.
>
> And this is mostly fine as long as you don't call functions from
> navigated-away-from windows. Which most people don't, most of the time.
> And when they do, they get _very_ confused by the results, because
> reality does not match what they had been told.
>
> But that doesn't mean we should double down on telling them things that
> don't match reality.
>
> > I strongly believe that things should be made intuitive for the vast
> > majority of users
>
> I agree, but in this specific context, what does that mean in terms of
> concrete proposals you are making?
>
> -Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxy Reflect.has() call causes infinite recursion?

2019-11-21 Thread #!/JoePea
Sorry you all, I realized I should've simplified it. Here's a [simpler
fiddle](https://jsfiddle.net/trusktr/tf6hdn48/6/).

On Thu, Nov 21, 2019 at 1:17 PM #!/JoePea  wrote:
>
> I was trying to implement "multiple inheritance" in the following code
> ([jsfiddle](https://jsfiddle.net/trusktr/tf6hdn48/)), but it gives a
> max call stack (infinite recursion) error.
>
> However, the infinite recursion does not execute any of my console.log
> statements repeatedly like I'd expect, so it seems that the infinite
> recursion is happening inside the JS engine?
>
> What's going on?
>
> Here's the code for reference, see "PROXY INFINITE RECURSION" comments
> for the site where the problem is happening (as far as I can tell in
> devtools):
>
> ```js
> "use strict";
>
> function multiple(...classes) {
> if (classes.length === 0)
> return Object;
> if (classes.length === 1) {
> const result = classes[0];
> return (typeof result === 'function' ? result : Object);
> }
>
> const FirstClass = classes.shift();
> const __instances__ = new WeakMap();
> const getInstances = (inst) => {
> let result = __instances__.get(inst);
> if (!result)
> __instances__.set(inst, (result = []));
> return result;
> };
>
> class MultiClass extends FirstClass {
> constructor(...args) {
> super(...args);
>
> const protoBeforeMultiClassProto =
> findPrototypeBeforeMultiClassPrototype(this, MultiClass.prototype);
> if (protoBeforeMultiClassProto)
> Object.setPrototypeOf(protoBeforeMultiClassProto,
> newMultiClassPrototype);
>
> const instances = getInstances(this);
>
> for (const Ctor of classes)
> instances.push(new Ctor(...args));
> }
> }
>
> let count = 0;
> const newMultiClassPrototype = new Proxy({
> __proto__: MultiClass.prototype,
> }, {
> get(target, key, self) {
> if (count++ < 500) console.log(' --- get', key);
>
> if (Reflect.has(MultiClass.prototype, key))
> return Reflect.get(MultiClass.prototype, key, self);
>
> for (const instance of getInstances(self))
> if (Reflect.has(instance, key))
> return Reflect.get(instance, key, self);
>
> return undefined;
> },
>
> set(target, key, value, self) {
> console.log(' - set1', key, value);
>
> // PROXY INFINITE RECURSION HERE:
> console.log('h?',
> Reflect.has(MultiClass.prototype, key));
>
> console.log(' - set1.5', key, value);
>
> if (Reflect.has(MultiClass.prototype, key)) {
> return Reflect.set(target, key, value, self);
> }
>
> const instances = getInstances(self);
>
> for (const instance of instances) {
> if (Reflect.has(instance, key)) {
> return Reflect.set(instance, key, value, self);
> }
> }
>
> return Reflect.set(target, key, value, self);
> },
> });
>
> return MultiClass;
> }
>
> function findPrototypeBeforeMultiClassPrototype(obj, multiClassPrototype) {
> let previous = obj;
> let current = Object.getPrototypeOf(obj);
> while (current) {
> // debugger
> if (current === multiClassPrototype)
> return previous;
> previous = current;
> current = Object.getPrototypeOf(current);
> }
> return null;
> }
>
> async function test() {
> await new Promise(r => setTimeout(r, 3000));
> console.log('-');
> const R1 = multiple();
> const r1 = new R1();
> console.log(Object.keys(r1));
> console.log('-');
> class Foo {
> constructor() {
> this.f = false;
> }
> }
> const R2 = multiple(Foo);
> const r2 = new R2();
> console.log(r2.hasOwnProperty);
> console.log('f', r2.f);
> console.log('-');
> class Bar {
> constructor() {
> this.b = 'asf';
> }
> }
> const R3 = multiple(Foo, Bar);
> const r3 = new R3();
> console.log(r3.hasOwnProperty);
> console.log('f', r3.f);
> console.log('b', r3.b);
> console.log('-');
> cla

Proxy Reflect.has() call causes infinite recursion?

2019-11-21 Thread #!/JoePea
I was trying to implement "multiple inheritance" in the following code
([jsfiddle](https://jsfiddle.net/trusktr/tf6hdn48/)), but it gives a
max call stack (infinite recursion) error.

However, the infinite recursion does not execute any of my console.log
statements repeatedly like I'd expect, so it seems that the infinite
recursion is happening inside the JS engine?

What's going on?

Here's the code for reference, see "PROXY INFINITE RECURSION" comments
for the site where the problem is happening (as far as I can tell in
devtools):

```js
"use strict";

function multiple(...classes) {
if (classes.length === 0)
return Object;
if (classes.length === 1) {
const result = classes[0];
return (typeof result === 'function' ? result : Object);
}

const FirstClass = classes.shift();
const __instances__ = new WeakMap();
const getInstances = (inst) => {
let result = __instances__.get(inst);
if (!result)
__instances__.set(inst, (result = []));
return result;
};

class MultiClass extends FirstClass {
constructor(...args) {
super(...args);

const protoBeforeMultiClassProto =
findPrototypeBeforeMultiClassPrototype(this, MultiClass.prototype);
if (protoBeforeMultiClassProto)
Object.setPrototypeOf(protoBeforeMultiClassProto,
newMultiClassPrototype);

const instances = getInstances(this);

for (const Ctor of classes)
instances.push(new Ctor(...args));
}
}

let count = 0;
const newMultiClassPrototype = new Proxy({
__proto__: MultiClass.prototype,
}, {
get(target, key, self) {
if (count++ < 500) console.log(' --- get', key);

if (Reflect.has(MultiClass.prototype, key))
return Reflect.get(MultiClass.prototype, key, self);

for (const instance of getInstances(self))
if (Reflect.has(instance, key))
return Reflect.get(instance, key, self);

return undefined;
},

set(target, key, value, self) {
console.log(' - set1', key, value);

// PROXY INFINITE RECURSION HERE:
console.log('h?',
Reflect.has(MultiClass.prototype, key));

console.log(' - set1.5', key, value);

if (Reflect.has(MultiClass.prototype, key)) {
return Reflect.set(target, key, value, self);
}

const instances = getInstances(self);

for (const instance of instances) {
if (Reflect.has(instance, key)) {
return Reflect.set(instance, key, value, self);
}
}

return Reflect.set(target, key, value, self);
},
});

return MultiClass;
}

function findPrototypeBeforeMultiClassPrototype(obj, multiClassPrototype) {
let previous = obj;
let current = Object.getPrototypeOf(obj);
while (current) {
// debugger
if (current === multiClassPrototype)
return previous;
previous = current;
current = Object.getPrototypeOf(current);
}
return null;
}

async function test() {
await new Promise(r => setTimeout(r, 3000));
console.log('-');
const R1 = multiple();
const r1 = new R1();
console.log(Object.keys(r1));
console.log('-');
class Foo {
constructor() {
this.f = false;
}
}
const R2 = multiple(Foo);
const r2 = new R2();
console.log(r2.hasOwnProperty);
console.log('f', r2.f);
console.log('-');
class Bar {
constructor() {
this.b = 'asf';
}
}
const R3 = multiple(Foo, Bar);
const r3 = new R3();
console.log(r3.hasOwnProperty);
console.log('f', r3.f);
console.log('b', r3.b);
console.log('-');
class Baz {
constructor() {
this.z = 1;
}
}
const R4 = multiple(Foo, Bar, Baz);
const r4 = new R4();
console.log(r4.hasOwnProperty);
console.log('f', r4.f);
console.log('b', r4.b);
console.log('z', r4.z);
class One {
constructor(arg) {
this.one = 1;
console.log('One constructor');
// this.one = arg
}
foo() {
console.log('foo', this.one);
}
setVar() {
this.var = 'bright';
}
}
class Two {
constructor(arg) {
this.two = 2;
console.log('Two constructor');
// this.two = arg
}
bar() {
console.log('bar', this.two);
}
readVar() {
console.log(this.var); // should be "bright"
}
}
class Three extends Two {

Re: Custom Elements in Templates

2019-11-16 Thread #!/JoePea
This is indeed an ugly problem that I've faced when making Custom
Elements. The problem is: in templates, custom elements do not get
"upgraded" into their identity. They only get "upgraded" once they are
inserted into the live DOM.

The best you can do is make deferred code in your custom element
constructor to check for existing property values before overriding
them with getters/setters, and make sure to store the already-existing
values.

It would also help for your elements to emit a "ready" event, or
similar, once the constructor has fired, and consumer code can listen
for this event (on a parent element where it has bubbled to) to
finally begin using any of the custom element's APIs.

Yes, this is very ugly. I really dislike this about custom elements.
But once you learn how to abstract it, then you'll be beyond the
problem. Libraries like Polymer, SkateJS, etc, abstract this stuff
away, so that if you stick with their recommended APIs, you don't hit
the issue.

But yeah, discourse.wicg.io is a good place to ask. Another good place
to ask, where all vendors talk about the spec, is
github.com/w3c/webcomponents/issues.

All the best,
- Joe


On Tue, Sep 24, 2019 at 9:39 AM Isiah Meadows  wrote:
>
> You'd have better luck in https://discourse.wicg.io than here. This is about 
> the ECMAScript spec and JavaScript the language, not anything related to the 
> web platform at large.
>
> On Tue, Sep 24, 2019 at 09:55 Randy Buchholz  wrote:
>>
>> I’m putting a custom element in a template and then “selecting” it out to 
>> Window level. It seem to loose its identity as a custom element.
>>
>>
>>
>> ```
>>
>> // In page
>>
>> 
>>
>> 
>>
>> 
>>
>>
>>
>> 
>>
>> class MyElement extends HTMLElement {
>>
>> constructor() {
>>
>> super();
>>
>> }
>>
>> get Field() { return this.getAttribute("field");}
>>
>> }
>>
>>
>>
>> window.customElements.define("my-element", MyElement);
>>
>> 
>>
>>
>>
>> 
>>
>> const frag = document.querySelector("#holder").content;
>>
>> const el = frag.querySelector("my-element");
>>
>> console.log({el});
>>
>> 
>>
>> ```
>>
>>
>>
>> When `` is a page level and not in a template I can read 
>> `xxx.Field`. When it comes from within a template it seems to no longer act 
>> like the custom element – xxx.Field isn’t defined. The script selecting it 
>> is at “Window” level, so shouldn’t it “cast” correctly?
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
> --
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
> ___
> 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: Conditional await, anyone?

2019-11-16 Thread #!/JoePea
I haven't read the whole thread, but I also disliked the ugly
conditional checking I had to do to get faster results.

I agree that this would changed perceived code execution order
(unexpectedly, a breaking change).

I believe that a better solution would be to make it explicit in the
function definition, so that it carries up into caller code:

```js
async? function foo() { ... }
```

Now, the user of the function must be required to use `await?` and
thus has to be forced to think that the `foo` function might possibly
run async, or might not. Using `await` on an `async? function` would
be a runtime error, to further prevent possible confusion and errors.

Only with a construct like `async? function` could I see this becoming
possible, so that there aren't any surprising breaking changes in
downstream projects.

On Tue, Oct 15, 2019 at 12:26 AM Andrea Giammarchi

 wrote:
>
> > You still seem to be misunderstanding what the execution order difference 
> > is about.
>
> If to stop this thread you need me to say I am confused about anything then 
> fine, "I am confused", but if you keep changing my examples to make your 
> point then this conversation goes nowhere, so I am officially out of this 
> thread.
>
> Best Regards.
>
> On Mon, Oct 14, 2019 at 10:41 PM Tab Atkins Jr.  wrote:
>>
>> On Sat, Oct 12, 2019 at 7:19 AM Andrea Giammarchi
>>  wrote:
>> > in order to work, `await` must be executed in an async scope/context 
>> > (either top level or within a closure).
>> >
>> > In such case, either somebody is awaiting the result of that `async` 
>> > execution, or the order doesn't matter.
>>
>> That's definitely not true. I gave you an explicit example where the
>> order differs. That example code is realistic if you're using the
>> async call for side-effects only (and thus don't care about the
>> returned promise), or if you're storing the returned promise in a
>> variable so you can pass it to one of the promise combinators later.
>> In either of these cases the order of execution between the sync and
>> async code can definitely matter.
>>
>> > The following two examples produce indeed the very same result:
>> >
>> > ```js
>> > (async () => { return 1; })().then(console.log);
>> > console.log(2);
>> >
>> > (async () => { return await 1; })().then(console.log);
>> > console.log(2);
>> > ```
>>
>> In both of these cases, you're doing no additional work after the
>> "maybe async" point. That is the exact part that moves in execution
>> order between the two cases, so obviously you won't see any
>> difference.  Here's a slightly altered version that shows off the
>> difference:
>>
>> ```js
>> (async () => { 1; console.log("async"); return 3; })().then(console.log);
>> console.log(2);
>>
>> (async () => { await 1; console.log("async"); return 3; 
>> })().then(console.log);
>> console.log(2);
>> ```
>>
>> In the first you'll log "async", "2", "3". In the second you'll log
>> "2", "async", "3".
>>
>> > As summary: the proposal was to help engines be faster when it's possible, 
>> > but devs are confused by the syntax, and maybeat the end there wouldn't be 
>> > as many benefits compared to the apparent confusion this proposal would 
>> > add.
>>
>> You still seem to be misunderstanding what the execution order
>> difference is about. Nobody's confused about the syntax; it's clear
>> enough. It just does bad, confusing things as you've presented it.
>>
>> As I said in earlier message, there *is* a way to eliminate the
>> execution-order difference (making it so the only difference would be
>> the number of microtasks when your function awaits *multiple* sync
>> values), which I thought you'd come up with at some point, but I'm
>> pretty sure it was just me misunderstanding what you'd said.
>>
>> ~TJ
>
> ___
> 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: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-11-16 Thread #!/JoePea
> Well, the thing that globalThis returns is NOT the global object, and
telling people that it is will just confuse them when it behaves in a
way they don't expect.

Hello Boris, thanks for your opinion and thoughts!

That's the thing: the only people that may get confused are Ecmascript
and JS-Engine experts who know the internals very intimately. I've
been making web applications for a long time, and have never had to
think about the concept that you've described. I continue to believe
that *the vast majority* of web developers would never get confused,
and for those people that could possibly get confused, it would be
because they are familiar with browser internals (or hit a browser
*bug* like you describe), and in the first case they actually won't be
confused because they are familiar with engine internals, and in the
second case browsers need to not create bugs like that.

For all intents and purpose, every developer I've talked to, and every
article I've read, treats things like `window` as the global object.
It's as simple as that 99.99% of the time.

I strongly believe that things should be made intuitive for the vast
majority of users, not the very few experts who know enough not to be
confused, or the very few people hitting a browser bug that should in
all honesty be patched in effort to make things easy for end
developers.

All the best,
- Joe

On Mon, Oct 7, 2019 at 1:11 PM Boris Zbarsky  wrote:
>
> On 10/7/19 1:56 PM, #!/JoePea wrote:
> > Who's going to write code like that anyways?
>
> In the general form of "function from a navigated-away-from document
> runs because it's called by some script from outside the document", I've
> seen this come up a number of times in web browser bug reports.
>
> > Everyone's moving to ES modules, where `this` for accessing the global
> > is just `undefined`.
>
> It's not just "this".  The same thing applies to "window", "self", etc,
> etc.  There is no way to actually get your hands on the global object
> explicitly in a DOM Window scope: you always get the WindowProxy instead.
>
> > It's highly unlikely that any concept other than
> > "global object" will ever be conceived by the vast majority of users,
> > especially future users.
>
> Well, the thing that globalThis returns is NOT the global object, and
> telling people that it is will just confuse them when it behaves in a
> way they don't expect.
>
> -Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [proposal-idea] Variable decorators

2019-11-16 Thread #!/JoePea
Any one have any thoughts on this?

On Fri, Oct 4, 2019 at 11:54 AM #!/JoePea  wrote:
>
> Currently we can implement things like "reactive variables" and
> "reactive computations". Contrived example:
>
> ```js
> import {rv, computation} from './reactive-variable'
>
> const count = rv(0)
>
> // read the value
> console.log(count()) // 0
>
> // set the value
> count(1)
> console.log(count()) // 1
>
> // increment it every second
> setInterval(() => count(count() + 1), 1000)
>
> // logs the value initially (1), and any time it is updated by the
> interval after that.
> computation(() => {
>   console.log(count())
> })
> ```
>
> And we can do neat things like compile JSX to using reactive computations:
>
> ```jsx
> const div = The count is: {count}
> document.body.append(div)
> ```
>
> and now the div's `textContent` updates every second with the new value.
>
> It'd be neat if we had variable accessors as well as variable decorators.
>
> The above example could become:
>
> ```jsx
> import {rv, computation} from './reactive-variable'
>
> // The rv variable decorator may implement this using a variable accessor
> // We can already do this with class properties/fields when
> transpiling class-based decorators
> @rv const count = 0
>
> // read the value
> console.log(count) // 0
>
> // set the value
> count = 1
> console.log(count) // 1
>
> // increment it every second
> setInterval(() => count++, 1000)
>
> // logs the value initially (1), and any time it is updated by the
> interval after that.
> computation(() => {
>   console.log(count)
> })
>
> const div = The count is: {count}
> document.body.append(div)
> ```
>
> variable accessors may look something like
>
> ```js
> // it is exportable just like regular variables
> export let s {
>   set(v) {
> console.log('set s:', v * 2)
> // maybe `this` is an engine-builtin object for this specific
> variable, that we can use to store stuff on.
> this.s = v * 2
>   },
>   get() {
> console.log('get s:', this.s)
> return this.s
>   },
> } = 0
> ```
>
> A variable decorator would have some way to be able to define a getter/setter.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-10-07 Thread #!/JoePea
Who's going to write code like that anyways?

Everyone's moving to ES modules, where `this` for accessing the global
is just `undefined`. It's highly unlikely that any concept other than
"global object" will ever be conceived by the vast majority of users,
especially future users.

On Fri, Oct 4, 2019 at 12:33 PM Boris Zbarsky  wrote:
>
> On 10/4/19 2:39 PM, #!/JoePea wrote:
> >> but the global `this` you captured still has the same identity as the new 
> >> reference.
> >
> > Interesting, I never knew that. Do you have a code sample to show how
> > to detect or prove that?
>
> Sure.  The following code logs "true, 5, 5, 5, 5, true, undefined,
> undefined, undefined, 5" in Firefox, Chrome, and Safari, which shows
> both the identity staying the same and the property disappearing from
> the WindowProxy, as well as showing the difference between the
> WindowProxy and the Window (the bareword lookup finds the var on the
> global, which is the Window, while `self.something` goes through the
> WindowProxy, which now points to the new `Window`):
>
> 
> 
>
>  var state = "first-load";
>  var cachedThis;
>  var cachedValueGetter;
>  var cachedBarewordGetter;
>  function loadHappened(iframe) {
>var win = iframe.contentWindow;
>
>if (state == "first-load") {
>  cachedThis = win.getGlobalThis();
>  cachedValueGetter = win.getPropertyValue;
>  cachedBarewordGetter = win.getBareword;
>  console.log(win == cachedThis);
>  console.log(win.something);
>  console.log(cachedThis.something);
>  console.log(cachedValueGetter());
>  console.log(cachedBarewordGetter());
>  state = "second-load";
>  iframe.srcdoc = iframe.srcdoc.replace("var something = 5;", "");
>  return;
>}
>
>console.log(frames[0] == cachedThis);
>console.log(frames[0].something);
>console.log(cachedThis.something);
>console.log(cachedValueGetter());
>console.log(cachedBarewordGetter());
>  }
>
>   onload="loadHappened(this)">
> 
>
> -Boris
> ___
> 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: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-10-07 Thread #!/JoePea
I didn't see it. For some reason my gmail thread split into two
separate threads, and I read one before the other.

On Mon, Oct 7, 2019 at 7:14 AM Boris Zbarsky  wrote:
>
> On 10/7/19 1:29 AM, #!/JoePea wrote:
> > I've never written any sort of code that can prove or verify any of
> > what you all are talking about. Mind showing code samples?
>
> Did you not see
> https://mail.mozilla.org/pipermail/es-discuss/2019-October/053033.html ?
>
> -Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-10-06 Thread #!/JoePea
Ah, this thread got forked from the other one, which has a code
sample. Taking a look at that...

On Sun, Oct 6, 2019 at 10:29 PM #!/JoePea  wrote:
>
> I never knew any of all that stuff you have all mentioned, and as an
> end user, I don't think I would ever need to know. To me, I use
> `window` as a global object, and it has never been more than that.
>
> I've never written any sort of code that can prove or verify any of
> what you all are talking about. Mind showing code samples?
>
> If a sample of code isn't possible, or if to the end user there's
> really just some single global object as far as their code is
> concerned, then "global object" is in fact a good name. That's why I'd
> like to see how what has been said actually manifests itself in
> end-user code.
>
> On Sun, Oct 6, 2019 at 1:43 PM Boris Zbarsky  wrote:
> >
> > On 10/6/19 2:58 PM, Raul-Sebastian Mihăilă wrote:
> > > Also let's not forget that the WindowProxy behavior contradicts the JS
> > > object model in that the non-configurable 'something' own property of
> > > the window proxy is removed.
> >
> > There is a proposal for addressing that.  Firefox has been shipping it
> > in Nightly for a while, but we have seen zero interest from any other
> > browsers for addressing that issue...
> >
> > See https://github.com/tc39/ecma262/pull/688#issuecomment-430648819 and
> > following comments for the details of the proposal.
> >
> > -Boris
> > ___
> > 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: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-10-06 Thread #!/JoePea
I never knew any of all that stuff you have all mentioned, and as an
end user, I don't think I would ever need to know. To me, I use
`window` as a global object, and it has never been more than that.

I've never written any sort of code that can prove or verify any of
what you all are talking about. Mind showing code samples?

If a sample of code isn't possible, or if to the end user there's
really just some single global object as far as their code is
concerned, then "global object" is in fact a good name. That's why I'd
like to see how what has been said actually manifests itself in
end-user code.

On Sun, Oct 6, 2019 at 1:43 PM Boris Zbarsky  wrote:
>
> On 10/6/19 2:58 PM, Raul-Sebastian Mihăilă wrote:
> > Also let's not forget that the WindowProxy behavior contradicts the JS
> > object model in that the non-configurable 'something' own property of
> > the window proxy is removed.
>
> There is a proposal for addressing that.  Firefox has been shipping it
> in Nightly for a while, but we have seen zero interest from any other
> browsers for addressing that issue...
>
> See https://github.com/tc39/ecma262/pull/688#issuecomment-430648819 and
> following comments for the details of the proposal.
>
> -Boris
> ___
> 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


[proposal-idea] Variable decorators

2019-10-04 Thread #!/JoePea
Currently we can implement things like "reactive variables" and
"reactive computations". Contrived example:

```js
import {rv, computation} from './reactive-variable'

const count = rv(0)

// read the value
console.log(count()) // 0

// set the value
count(1)
console.log(count()) // 1

// increment it every second
setInterval(() => count(count() + 1), 1000)

// logs the value initially (1), and any time it is updated by the
interval after that.
computation(() => {
  console.log(count())
})
```

And we can do neat things like compile JSX to using reactive computations:

```jsx
const div = The count is: {count}
document.body.append(div)
```

and now the div's `textContent` updates every second with the new value.

It'd be neat if we had variable accessors as well as variable decorators.

The above example could become:

```jsx
import {rv, computation} from './reactive-variable'

// The rv variable decorator may implement this using a variable accessor
// We can already do this with class properties/fields when
transpiling class-based decorators
@rv const count = 0

// read the value
console.log(count) // 0

// set the value
count = 1
console.log(count) // 1

// increment it every second
setInterval(() => count++, 1000)

// logs the value initially (1), and any time it is updated by the
interval after that.
computation(() => {
  console.log(count)
})

const div = The count is: {count}
document.body.append(div)
```

variable accessors may look something like

```js
// it is exportable just like regular variables
export let s {
  set(v) {
console.log('set s:', v * 2)
// maybe `this` is an engine-builtin object for this specific
variable, that we can use to store stuff on.
this.s = v * 2
  },
  get() {
console.log('get s:', this.s)
return this.s
  },
} = 0
```

A variable decorator would have some way to be able to define a getter/setter.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-10-04 Thread #!/JoePea
> but the global `this` you captured still has the same identity as the new 
> reference.

Interesting, I never knew that. Do you have a code sample to show how
to detect or prove that?

On Sat, Sep 21, 2019 at 9:05 PM Isiah Meadows  wrote:
>
> If you look in the proposal's repo, they explain the rationale behind the 
> identifier:
> https://github.com/tc39/proposal-global/
>
> Here's a short summary: `globalThis` is the same value you get from 
> evaluating `this` in the global scope of a sloppy mode script. This is subtly 
> different than a "global object", which JS has no concept of. There's other 
> nuances involved, too.
>
> Concretely, for one example, `globalObject` was explicitly rejected because 
> in HTML, the global `this` is a proxy of `window`, not the `window` object 
> itself. The `window` proxy delegates all operations to the current global 
> `window`, as you might expect. But here's where things get interesting: 
> during navigation, the window changes, yet the global `this` does not, so if 
> you define a property, capture the global `this`, and navigate, the property 
> you just defined will disappear, but the global `this` you captured still has 
> the same identity as the new reference.
>
> This file in particular explains the naming side of it in detail:
> https://github.com/tc39/proposal-global/blob/master/NAMING.md It covers the 
> other suggested names here indirectly.
>
> And do keep in mind much of TC39's members are non-native speakers 
> themselves, including one of the proposal's biggest champions/fans, Matthias. 
> So it's not like that concern goes unnoticed - if anything, it gets accounted 
> for without them even thinking about it. It might also explain why it's 
> `array.entries()`, `map.entries()`, and similar when the more proper English 
> name would've been `array.pairs()`, `map.pairs()`, and so on: entries are 
> really what values from `value[Symbol.iterator]()` represent, and non-native 
> speakers sometimes misuse "entries" as if it were synonymous with "pairs". 
> Contrast this with Underscore's `_.pairs`, named by a native English speaker 
> back in 2012, long before ES6 was a thing, and it stood as precedent for 
> having `coll.entries()` for various collections.
>
> On Sat, Sep 21, 2019 at 14:12 #!/JoePea  wrote:
>>
>> I know it may be too late for this, but I imagine `globalThis` can bring 
>> confusion to beginners, especially ESL beginners.
>>
>> Things like `globalObject`, `systemGlobal`, or `globalEntity` would've been 
>> more intuitive; they make sense in plain English.
>>
>> Well anyways, have a good weekend!
>>
>> - Joe
>>
>>
>> ___
>> 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


Why globalThis instead of something intuitive like globalObject, systemGlobal, or globalEntity?

2019-09-21 Thread #!/JoePea
I know it may be too late for this, but I imagine `globalThis` can bring
confusion to beginners, especially ESL beginners.

Things like `globalObject`, `systemGlobal`, or `globalEntity` would've been
more intuitive; they make sense in plain English.

Well anyways, have a good weekend!

- Joe
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Promise resolution handler fires before synchronous constructor stack has finished.

2019-07-27 Thread #!/JoePea
I feel like I'm going crazy, but I have a class hierarchy, and one of
the constructors in the hierarchy defers some logic to a microtask,

```js
// class Foo
constructor() {
  Promise.resolve().then(() => {
this.methodThatSubclassOverrides()
  })
}

methodThatSubclassOverrides() {}
```

and in the subclass there is

```js
// class Bar extends Foo
constructor() {
  super()
  this.foo = 123
}

methodThatSubclassOverrides() {
  console.log(this.foo) // should be "123"
}
```

You'd think the output should be "123" because the deferred code will
run after construction is complete.

However, in my current project, the promise deferral seems to run
before the construction returns to the Bar constructor, thus this.foo
is not set, and calls `methodThatSubclassOverrides` before the Bar
class has a chance to run `this.foo = 123`. So the result of the
console.log is "undefined".

It is totally weird. Do Promises ever resolve before a constructor
stack finishes?

I don't have a simple reproduction at the moment.

- Joe
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Actual WeakSet Use Cases

2019-04-22 Thread #!/JoePea
(I edited the broken format of my previous post)

What other use cases are there?

On Mon, Apr 22, 2019 at 11:20 AM #!/JoePea  wrote:

> > WeakSets are perfect for branding and are how I would expect web
> platform class branding to be explained.
> >
> > ```js
> > const foos = new WeakSet();
> >
> > class Foo {
> >   constructor() {
> > foos.add(this);
> >   }
> >
> >   method() {
> > if (!foos.has(this)) {
> >   throw new TypeError("Foo.prototype.method called on an
> incompatible object!");
> > }
> >   }
> > }
> > ```
>
> Just curious, is that effectively the same as what the (current) [private
> fields proposal](https://github.com/tc39/proposal-class-fields) offers?
>
> ```js
> class Foo {
>   #isFoo = true
>
>   method() {
> if (this.#isFoo) {
>   throw new TypeError("Foo.prototype.method called on an incompatible
> object!");
> }
>   }
> }
> ```
>
> - Joe
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Actual WeakSet Use Cases

2019-04-22 Thread #!/JoePea
> WeakSets are perfect for branding and are how I would expect web platform
class branding to be explained.
>
> ```js
> const foos = new WeakSet();
>
> class Foo {
>   constructor() {
> foos.add(this);
>   }
>
>   method() {
> if (!foos.has(this)) {
>   throw new TypeError("Foo.prototype.method called on an incompatible
object!");
> }
>   }
> }
> ```

Just curious, is that effectively the same as what the (current) [private
fields proposal](https://github.com/tc39/proposal-class-fields) offers?

```js
class Foo {
  #isFoo = true

  method() {
if (this.#isFoo) {
  throw new TypeError("Foo.prototype.method called on an incompatible
object!");
}
  }
}
```

- Joe
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


A way to fire logic at the end of completion of the current class method (regardless of super call order).

2019-02-07 Thread #!/JoePea
I many times find myself in cases where a base class wants to ensure that
logic is always fired after the current method's execution, so that for
example no matter in which order sub classes call the `super` method, the
`super` method can still guarantee that logic fires after the whole stack
of the same method in the class hierarchy.

So what I can do now is use `Promise.resolve().then(() => { ... })` to
schedule that logic for later, that way all the invocations of a `foo`
method along the class hierarchy have all fired. But this means that other
code can also fire before the next microtask.

Is there some way to do it? If not, I wonder if some language feature for
doing it would be possible?

- Joe
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


idea: Array.prototype.remove

2019-02-03 Thread #!/JoePea
I sometimes find myself doing things like

```js
this.children.splice(this.children.indexOf(child), 1)
```

but it seems that it will iterate the array twice. Maybe a new method can
be introduced so engines can optimize it:

```js
this.children.remove(child)
// or
this.children.remove(...childrenToRemove)
```
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


returning non-Promise values from async functions and running them synchronously (or Promise.sync() idea)

2019-02-03 Thread #!/JoePea
I often find myself enjoying async functions until the time comes when I
don't want to await anything, and I want the call stack to be sync (i.e. I
don't want to defer if I don't have to).

But, async functions always return a Promise. So I find my self converting
my async functions back into normal functions so that I can return
non-Promise values, this way the caller can wait only if I return a
promise, otherwise continue synchronously.

Here's an example function in one of my classes:

```js
initWebGL() {
if (this.__glLoading) return false
this.__glLoading = true

// order of the if-else matters!
if (this.__glUnloading) return
Promise.resolve().then(A.bind(this))
else if (this.__glLoaded) return false

A.call(this)

function A() {
// ... load stuff (omitted for brevity) ...
}

return true
}
```

then the caller (f.e. a subclass) only needs to wait when a promise is
returned:

```js
initWebGL() {
const superResult = super.initWebGL()
if (superResult instanceof Promise) return
superResult.then(A.bind(this))
if (!superResult) return false

A.call(this)

function A() {
// ... subclass loads stuff (omitted for brevity) ...
}

return true
}
```

This is just one example, but in general I find many cases where I want to
run synchronously most of the time, and only sometimes have to defer
(whether by choice or not).

So I am losing out on the nice `await` syntax just because I can not do
what I want to do with `async`/`await`.

What if async functions could have some way to continue synchronously, and
return non-Promise values?

Or, what if we could have some sort of Promise API that would cause any
callers to synchronously away, like in the following example, so that the
change is not a breaking change, and async functions would still return
Promises but the Promise could perhaps continue synchronously:

```js
async function example() {
  return Promise.sync()
}
```

Then, in a caller, there would be no microtask deferral:

```js
async function test() {
  await example()
  console.log('one')
  // implicit return is a Promise.sync() here.
}

function main() {
  test()
  console.log('two')
}
```

The output in this case would be:

```
"one"
"two"
```

Note that in that example, we are _sure_ that `two` is logged after `one`
because those async functions only ever use `Promise.sync()`.

It would be good practice to use `await` regardless, because one may not
know if the async function they are calling will return a
non-`Promise.sync` value. So the `main` function is better written as

```js
async function main() {
  await test()
  console.log('two')
}
```

In this case, everything still happens synchronously, but if the author of
`example()` changes the implementation to return a non-sync Promise, then
things will still run in the expected order. F.e.

```js
async function example() {
  await fetch(...)
}
```

I keep finding scenarios where I want to avoid async unless I need async,
but then I lose the convenient async/await syntax.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


How to prettify output of objects in the console, when using get/set, like browsers do?

2019-01-09 Thread #!/JoePea
Here's some nice output in the console in Chrome, for `DOMPoint` and
`DOMPointReadOnly` classes:

```js
const point = new DOMPoint(1,2,3,4)
console.log(point)
```

output:

```
> DOMPoint {x: 1, y: 2, z: 3, w: 4}
```

([codepen example](https://codepen.io/anon/pen/xmaVej), open the devtools
console then re-run the example to see the "nice" output)

However if I use the my polyfill [here](
https://github.com/trusktr/geometry-interfaces/blob/master/src/DOMPoint.js),
then the output is not as helpful:

```js
const point = new DOMPoint(1,2,3,4) // uses polyfill
console.log(point)
```

output (notice, it does not show the x,y,z,w values):

```
> DOMPoint {}
```

([codepen example](https://codepen.io/anon/pen/QzVNeE), open the devtools
console then re-run the example to see the expected output)

When I expand the object in the console, I can see the getters, marked with
`(...)`, and I can click on them to trigger them, but the output is limited
and does not show the x,y,z,w values like the native one does.

Is it possible to make the output nice with the polyfill? Or does the
engine have internal mechanisms that we don't get to use in plain
JavaScript?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Polyfilling Object.observe

2018-07-28 Thread #!/JoePea
> Because you are doing it wrong.

Yeah, because using Proxy isn't simple like using `Object.observe`. I'm
just showing that this is all extremely easy to do with `Object.observe`.

> What you really want is to have new Foo() return a Proxy... which is
counter-intuitive, admittedly, because we're all taught that a constructor
should never explicitly return a value.

I mentioned earlier I don't want to modify my entire class hierarchy just
to make part of it observable, and have to tell people who extend my
classes to change their patterns (it's a breaking change).

Again, not a problem with `Object.observe`.

> membranes

I just read the articles. That's much too complicated. Plus, it only works
on objects that are designed to be proxies before they are passed to other
code.

I want to do this:

```js
import anyObject from 'any-package-on-npm'

Object.observe(anyObject, console.log)

// logs stuff every time any-package-on-npm modifies the object.
```

If I use proxy, this is what happens:


```js
import anyObject from 'any-package-on-npm'

const membrane = new ObservableMembrane({
  valueMutated: console.log
})

membrane.getProxy(anyObject)

// nothing, silence, crickets
```

`Object.observe` just works, and is s simple. I won't shoot
myself in the foot with it. I'd like to make a one-way data flow
implementation with it, using 3rd party web components, and
`Object.observe` would make this _incredibly simple_.

*/#!/*JoePea


On Sat, Jul 28, 2018 at 8:54 AM Alex Vincent  wrote:

>
> `Proxy` is powerful, but it's not as good as `Object.observe` would've
>> been for some very simple tasks.
>>
>> Every time I wish I could use `Proxy` in a simple way, there's always
>> some issue with it. For example: https://jsfiddle.net/trusktr/hwfontLc/17
>>
>
> Because you are doing it wrong.
>
> Proxies can *only* observe on the object that they're created for.  By
> setting Foo.prototype to a proxy, you can only observe operations on
> Foo.prototype, not instances of Foo.
>
> What you really want is to have new Foo() return a Proxy... which is
> counter-intuitive, admittedly, because we're all taught that a constructor
> should never explicitly return a value.
>
> This problem has been solved, a few times, with the introduction of
> membranes in JavaScript.  In that environment, you would start with Foo and
> wrap it in a membrane proxy. Then, in invoking new Foo(), the "construct"
> trap of that proxy would return another roxy automatically, probably using
> the same proxy handler but a different proxy target.
>
> If it's any consolation, proxies are in general very hard to work with.
> You're only scratching the surface here.  I recently gave a talk at TC39
> (the standards body for ECMAScript) on membranes.  One key takeaway is that
> the overhead in dealing with membrane-oriented proxies really is better off
> left to a library built for that purpose.
>
> Tom van Cutsem is working on an article summarizing the current state of
> membranes.  I'm not sure if he has approved its general release yet, so
> stay tuned...
>
> Alex Vincent
> Edmonds, WA (on vacation)
>
> --
> "The first step in confirming there is a bug in someone else's work is
> confirming there are no bugs in your own."
> -- Alexander J. Vincent, June 30, 2001
> ___
> 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: Polyfilling Object.observe

2018-07-27 Thread /#!/JoePea
nst propName of propertyNames) {
const descriptor = Object.getOwnPropertyDescriptor(object,
propName) || {}

if (descriptor[isObserved]) continue

let getValue
let setValue

if (descriptor.get || descriptor.set) {
// we will use the existing getter/setter assuming they don't do
// anyting crazy that we might not expect. (See? Another reason
for
// Object.observe)
const oldGet = descriptor.get
const oldSet = descriptor.set

getValue = () => oldGet.call(object)
setValue = value => oldSet.call(object, value)
}
else {
if (!map) map = new Map

const initialValue = descriptor.value
map.set(propName, initialValue)

delete descriptor.value
delete descriptor.writable

getValue = () => map.get(propName)
setValue = value => map.set(propName, value)
}

Object.defineProperty(object, propName, {
...descriptor,

get() {
return getValue()
},

set(value) {
setValue(value)
callback(propName, getValue())
},

[isObserved]: true,
})
}
}
```

And the usage looks like:

```js
const o = {
foo: 1,
bar: 2,
get baz() {
console.log('original get baz')
return this._baz
},
set baz(v) {
console.log('original set baz')
this._baz = v
},
}

observe(o, ['foo', 'bar', 'baz'], (propName, newValue) => {
console.log('changed value:', propName, newValue)
})

o.foo = 'foo'
o.bar = 'bar'
o.baz = 'baz'
```

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Polyfilling Object.observe

2018-07-27 Thread /#!/JoePea
Another caveat of my implementation, for example, is that it adds
getters/setters for properties that previously didn't exist. This will
break code that checks existence of props. etc. etc. That's not a problem
with a theoretical `Object.observe`.

*/#!/*JoePea


On Fri, Jul 27, 2018 at 10:53 AM /#!/JoePea  wrote:

> > I don't think there's any solution other than diffing
>
> And how would you diff without polling (while supporting IE)?
>
> `Proxy` is powerful, but it's not as good as `Object.observe` would've
> been for some very simple tasks.
>
> Every time I wish I could use `Proxy` in a simple way, there's always some
> issue with it. For example: https://jsfiddle.net/trusktr/hwfontLc/17
>
> Why do I have to sacrifice the convenience of writing ES6 classes just to
> make that work? And plus that introduced an infinite recursion that I
> overlooked because I didn't treat the get/set the same way as we should
> treat getters/setters and store the value in a different place. It's just
> more complicated than `Object.observe`.
>
> If we want to use ES6 classes, we have to come up with some convoluted
> pattern for returning a Proxied object from a constructor possibly deep in
> a class hierarchy, so that all child classes can use the proxied `this`.
>
> Using `Proxy` like this is simply not ideal compared to `Object.observe`.
>
> > not exactly the same as Object.observe
>
> Yep :)
>
> > When you diff is totally up to your use case
>
> I'd like performant change notifications without interfering with object
> structure (f.e. modifying descriptors) or without interfering with the way
> people write code. I want to have synchronous updates, because that gives
> me the ability to opt-in to deferring updates. If the API is already
> deferred (f.e. polling like in the official and deprecated Object.observed
> polyfill), then there's not a way to opt-in to synchronous updates.
>
> I simply would like to observe an object with a simple API like:
>
> ```js
> import someObject from 'any-npm-package-that-could-ever-exist'
>
> const thePropsIWantToObserve = ['foo', 'bar', 'baz']
>
> Object.observeProps( someObject, thePropsIWantToObserve, (name, oldValue,
> newValue) => {
>   console.log('property on someObject changed:', name, oldValue, newValue)
> })
> ```
>
> I'd be fine if it only gave me two args, `name` and `newValue`, and I
> could optionally cache the oldValue myself if I really wanted to, which
> automatically saves resources by making that opt-in. I'd also want it to be
> at the very least triggering observations on a microtask. Synchronous would
> be better, so I can opt-in to deferring myself. Maybe and option can be
> passed in to make it synchronous.
>
> ---
>
> I won't shoot myself in the foot with `Object.observe`. I know what I plan
> to do with the gun, if it ever comes to exist. If one builds a tank (an
> API) and places a user in it, that user can't shoot themselves in the foot,
> can they? (I'm anti-war pro-peace and against violence, that's just an
> analogy.) It's like a drill: sure, some people aren't very careful when
> they use drills the wrong way and hurt themselves? What about the people
> who know how to use the drills? Maybe we're not considering those people
> when deciding that drills should be outlawed because one person hurt
> themselves with one.
>
> Let's let people who know what they're doing make good use of the tool. A
> careless programmer will still shoot themselves in the foot even without
> Object.observe. There's plenty of ways to do it as is.
>
> If someone can currently implement `Object.observe` by using polling with
> diffing, or by hacking getter/setter descriptors, why not just let them
> have the legitimate native implementation? For people who are going to
> shoot their foot off anyways, let's let them at least impale their foot
> efficiently instead of using a spoon, while the professionals can benefit
> from the tool.
>
> We've got libs like Backbone.js that make us write things like
> `someObject.set('foo', 123)` so that we can have the same thing as
> `Object.observe` provides. Backbone was big. This shows that there's people
> that know how to use the pattern correctly. This is another example of a
> library author having to tell end users to write code differently in order
> to achieve the same goal as we'd simply have with `Object.observe`:
> ideally we'd only need to write `someObject.foo = 123` which saves both
> the author of `someObject` and the consumer of `someObject` time.
>
> It'd simply be so nice to have `Object.observe` (and preferably a simpler
> version, like my following example).
>
> So for my use case, I'll use the following small implementation. You may
>

Re: Polyfilling Object.observe

2018-07-24 Thread /#!/JoePea
> But yes, **if** you know the names of the properties in advance

I don't because I'm using [`element-behaviors`](
https://github.com/trusktr/element-behaviors) (which I wrote). Behaviors
can be arbitrarily added and removed from an element, behaviors can observe
any arbitrary attributes on an element, but the difficulty is in behaviors
observing arbitrary properties on an element regardless of if the props
already exist. Because an element may have any number of unknown behaviors
added to it in the future, there's no way to pre-meditate the set of props
that will be observed.

> The only way I can think of that might work will only work if all actions
against the observed object happen through methods of the observed object's
prototype

If I drop support for IE, maybe Proxy will help me.

The thing is, what are the implications? It seems a bit tricky to introduce
a Proxy somewhere in the middle of a class hierarchy.

- How do I return a Proxied this from a class in the middle of a hierarchy
without changing patterns? Seems like I could use a single base
`constructor` then move all construction logic to a `construct` method
called by the base `constructor`, to make things easier. I do a similar
hack now anyways in order to make ES5-style classes work with native Custom
Elements.
- How do we proxify a class prototype when using ES6 classes? Do we just
`SomeClass.prototype = new Proxy(SomeClass.prototype, handler)`? Any
implications of that?
- Seems like `Object.observe` would've just been the easiest way to achieve
what I want, if that hadn't been dropped.
- I currently use `MutationObserver` to observe HTML element attribute
changes, which is the like the equivalent of `Object.observe` for DOM. But
the downside of this is that it only covers attributes, not instance
properties. Plus, attributes are always strings, incurring performance
overhead. And all the new frameworks delegate to instance properties,
bypassing attributes, therefore bypassing MutationObserver observations.

Seems like `Object.observe` would be the simple magic tool that I keep
circling back to.

In my specific use case (the behaviors), I'd just like to observe arbitrary
instance props so that I can get performance gains from not observing
attribute changes in cases where a framework is using instance props
instead of attributes. Again, attributes are arbitrarily observable, while
props are not.

If I am okay to drop support for IE (I'm a little skeptical), then I'd like
to consider how Proxy might help, but it just seems more complicated that
it ought to be compared to `Object.observe` (which my behaviors could use
to observe elements).

*/#!/*JoePea


On Tue, Jul 24, 2018 at 10:17 AM T.J. Crowder <
tj.crow...@farsightsoftware.com> wrote:

> On Tue, Jul 24, 2018 at 6:01 PM, /#!/JoePea
>  wrote:
> > Is there a way to polyfill `Object.observe` in such a way that the object
> > before observation is the same reference as the object being observed
> after
> > the call (i.e. not a Proxy), and other than monkey-patching
> getters/setters?
> >
> > Is defining getters/setters the only way?
>
> Even that doesn't really polyfill it, because `Object.observe` got
> notifications of changes when new properties were created as well.
>
> But yes, **if** you know the names of the properties in advance (the
> "shape" of the object, I believe, is the current parlance?), and if you
> want notifications of changes just to those properties, I think
> monkeypatching will be your simplest and most successful approach.
>
> If you need to catch additions as well, I don't think there's any solution
> other than diffing, which is quite yucky.
>
> -- T.J. Crowder
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Polyfilling Object.observe

2018-07-24 Thread /#!/JoePea
Is there a way to polyfill `Object.observe` in such a way that the object
before observation is the same reference as the object being observed after
the call (i.e. not a Proxy), and other than monkey-patching getters/setters?

Is defining getters/setters the only way?

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Share a secret across ES6 specific modules, so that other modules cannot access the secret?

2018-04-16 Thread /#!/JoePea
I think it'd be nice if there was something also easier, based only on file
names or directory structure.

```js
// log-foo.js
import Foo from './Foo'
console.log(Foo)
```

```js
// Foo.js
class Foo {}
export Foo for './log-foo'

// or with expressions, all files in this folder
export Foo for './*'
```

I know, someone can stick a file in there then, but at least it gives a
"don't mess with this unless you know what you're doing" message like many
other things in JavaScript (f.e. redefining a configurable property even if
writable is false).

We'll, I suppose even with public keys, a use can just replace your module
in the file system with their own, so the same "be careful" principal still
applies there.

Of course, network-modules won't have the filesystem-module problem, so
probably both filename approach and box approach would be secure with
network modules (just needs infrastructure for passing that info around).

On Sun, Apr 15, 2018, 11:58 AM Mike Samuel <mikesam...@gmail.com> wrote:

> The box function defined in github.com/mikesamuel/tc39-module-keys
> enables things like this.
>
>
> On Sun, Apr 23, 2017 at 4:42 PM, /#!/JoePea <j...@trusktr.io> wrote:
>
>> Is there a way to share some secret value across a few modules, and
>> prevent other modules? f.e. prevent modules of an app dev who is importing
>> modules of a library where the library wants to share private stuff across
>> its modules. Is this possible to implement somehow?
>>
>> WeakMaps can be encapsulated inside a module to implement "private"
>> properties for a class defined inside that module and then exported. But
>> "protected" can't be implemented with a WeakMap shared with modules because
>> then end-user app code can import the WeakMap and read all the stuff. Is
>> there some way to share a WeakMap private with classes defined across
>> modules?
>>
>> */#!/*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: Share a secret across ES6 specific modules, so that other modules cannot access the secret?

2018-04-15 Thread /#!/JoePea
Ah, interesting! That would be useful!

*/#!/*JoePea

On Sun, Apr 15, 2018 at 11:58 AM, Mike Samuel <mikesam...@gmail.com> wrote:

> The box function defined in github.com/mikesamuel/tc39-module-keys
> enables things like this.
>
>
> On Sun, Apr 23, 2017 at 4:42 PM, /#!/JoePea <j...@trusktr.io> wrote:
>
>> Is there a way to share some secret value across a few modules, and
>> prevent other modules? f.e. prevent modules of an app dev who is importing
>> modules of a library where the library wants to share private stuff across
>> its modules. Is this possible to implement somehow?
>>
>> WeakMaps can be encapsulated inside a module to implement "private"
>> properties for a class defined inside that module and then exported. But
>> "protected" can't be implemented with a WeakMap shared with modules because
>> then end-user app code can import the WeakMap and read all the stuff. Is
>> there some way to share a WeakMap private with classes defined across
>> modules?
>>
>> */#!/*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: Share a secret across ES6 specific modules, so that other modules cannot access the secret?

2018-04-15 Thread /#!/JoePea
> GATEWAY

That's an interesting idea, Bradley, thanks! I originally wanted this for
implementing "protected" class members (i.e. sharing a WeakMap across
subclasses in different files), but I've since done this another way that
is even better: https://github.com/trusktr/lowclass.

With lowclass we can also make what I'm calling "module protected" access
(similar to "friends" in C or "package protected" in Java) by simply
leaking access helpers to outside scope inside a module. Here's the example
in the README
<https://github.com/trusktr/lowclass#friends-like-in-c-or-package-protected-like-in-java>
.

But now that I've revisited this thread, I realize that with a GATEWAY it
is possible to share a "leaked" access helper across files too, thus making
something that is more like Java's "package protected"! Cool!

> note: all dependencies of these modules could access GATEWAY

This can be prevented by having the `GATEWAY` function count how many times
it is called. If we hard code the number of modules that will call GATEWAY
in a project, we can throw an error if the number of accesses is higher
than expected and blatantly breaking an app to force people not to do it.
Automated tests can ensure that the number is hard coded properly. It could
also be possible to add a build step to automatically detect and add the
hard-coded number.

> With Realms

That's also interesting, but I think it would be too heavy-weight to create
new JS contexts just for sharing some private references. The GATEWAY idea
I think is much slimmer. Plus sharing across Realms can introduce all sorts
of other problems like `instanceof` checks failing due to one global not
being the same reference to the equivalent global in the other realm
(`console.assert(window.Object !== realm.Object)`). Here's is the same
problem with Jest <https://github.com/facebook/jest/issues/5946> (with
Node's `vm` rather than Realms, but essentially its the same issue).

It'd be better if there were some sort of spec added to Modules that
allowed some set of modules to import private exports from each other with
simple syntax, or similar. Maybe it would be based on folder structure, or
maybe module identifiers referenced in each other so that there's no
physical circular dependency, only harmless circular mentioning of each
other at worst, so that runtime circular dependency issues
<https://esdiscuss.org/topic/how-to-solve-this-basic-es6-module-circular-dependency-problem>
don't become a problem.

> If you are interested to look at it, I’ve implemented a module loader
with a secret shared across the Doodad framework

Thanks for sharing that Claude. It's interesting to see how others are
implementing public/protected/private for their classes. :)

- Joe

*/#!/*JoePea

On Mon, Apr 24, 2017 at 12:34 PM, Bradley Meck <bradley.m...@gmail.com>
wrote:

> To an extent, yes. You can use hoisting of function declarations and
> circular dependencies to create a "gateway". During circular dependencies,
> you have a time where function declarations are available but evaluation
> has not occured. During that time you can setup your private state. Then,
> immediately on evaluation, remove your gateway.
>
> ```
> // file: ./secrets
>
> // import all friendly modules (note: all dependencies of these modules
> could access GATEWAY)
> import './a'
> GATEWAY = void 0;
>
>
> // storage for shared secrets
> let SECRET;
> // gateway
> function GATEWAY() {
>   if (!SECRET) SECRET = {};
>   return SECRET;
> }
> export {GATEWAY};
> ```
>
> ```
> // file: ./a
> import {GATEWAY} from './secrets';
> if (typeof GATEWAY !== 'function') {
>   throw Error('import secrets *first*.');
> }
> const SECRET = GATEWAY();
> ```
>
> With Realms (https://github.com/tc39/proposal-realms) you may be able to
> use the completion value of Module Evaluation to also achieve a way to
> share private state in a more sane way. VM implementations allow this in
> some ways as well : https://github.com/v8/v8/blob/
> a71c338d9e24e55b47125108a0fce754076751d0/include/v8.h#L1109
>
> On Sun, Apr 23, 2017 at 6:02 PM, Jordan Harband <ljh...@gmail.com> wrote:
>
>> Nope. This is exactly why it seems that "protected" couldn't have any way
>> to work that has "hard" enforcement.
>>
>> The only true privacy in JS is via closure (including WeakMaps), or via
>> the upcoming "private fields" proposal, assuming it stays as "hard
>> private". Anything shared is publicly accessible.
>>
>> I'd be very interested to hear any idea that would allow modules A and B
>> to privately share something, without module C being able to; the only
>> thing I could think of would be some sort of private export that

Re: extending an ES6 class using ES5 syntax?

2018-04-02 Thread /#!/JoePea
Ah, makes sense. Thanks! - Joe

*/#!/*JoePea

On Thu, Mar 29, 2018 at 9:53 PM, Rob Brackett <r...@robbrackett.com> wrote:

> Why is it that the static version you implemented above can `.apply`
> itself without this same error (and `new` is not being used)?
>
>
> Wow, this is old stuff! Anyway, it’s because it never calls the built-in
> `apply` on itself:
>
> ```
> class FunctionInheritable {
>   //…other bits omitted…
>
>   static apply(context, args) {
> // this calls `apply` on `_constructor`, which is a function, not
> `constructor`, which is a class constructor
> return this.prototype._constructor.apply(context, args) || context;
>   }
> }
> ```
>
> -Rob
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


How many ES5 environments are still in use today?

2018-04-02 Thread /#!/JoePea
I'm curious to know how many pure ES% environments (with or without
non-standard features like __proto__, and without any ES6 features) are
still being used in the wild.

Would this come down to a browser statistics lookup? I believe there are
other projects that use ES, like Rhino, Espruino, etc. Do you know of some
place to get such statistics besides for browsers?

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: extending an ES6 class using ES5 syntax?

2018-03-28 Thread /#!/JoePea
​Rob, you gave an example (I modified barely, to make it work in browser
console):

```js
class FunctionInheritable {
  constructor() {
return this._constructor.apply(this, arguments);
  }
  _constructor() {}
  static call(context, ...args) {
return this.apply(context, args);
  }
  static apply(context, args) {
return this.prototype._constructor.apply(context, args) || context;
  }
}

class YourActualLibraryClass extends FunctionInheritable {
  // all your inheritable classes will have to use `_constructor` instead
of `constructor`
  _constructor(firstArg) {
// do whatever you want, there are no special requirements on what’s in
here
this.something = firstArg;
  }
  someLibraryClassFunction() {
return this.something;
  }
}

// any ES5 or earlier function-style “class” can now inherit with no changes
function SomeEs5FunctionConstructor() {
  this.somethingElse = 'whatever';
  YourActualLibraryClass.call(this, 'something');
}
SomeEs5FunctionConstructor.prototype =
Object.create(YourActualLibraryClass.prototype);​

new SomeEs5FunctionConstructor().someLibraryClassFunction() // "something"
```

It works, but I don't understand why. For example, if I try the following,
it fails:

```js
class Foo {}
Foo.apply(window, ['foo'])
```

Why is it that the static version you implemented above can `.apply` itself
without this same error (and `new` is not being used)?

- Joe


*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Object.unfreeze, or similar API

2018-03-24 Thread /#!/JoePea
I see, so you're relying on the engine reading the handler object during
the moment that the user of my `obj` will try to read `obj`, so if the
engine tries to read something in the handler (that we haven't whitelisted)
due to what the user is doing with `obj` then we throw the error. If the
engine were to read these all in advance, this would cause a problem. Are
we sure that all engines don't read the handler spec in advance?

*/#!/*JoePea

On Sat, Mar 24, 2018 at 2:59 PM, Oriol _ <oriol-bugzi...@hotmail.com> wrote:

> Hi Joe, I used a 2nd proxy as the handler in order to only allow the
> desired traps.
>
> Sure, I could have defined all blacklisted traps in an ordinary object,
> and make them throw an error.
>
> But this wouldn't be future-proof in case new traps are eventually added.
> Whitelisting is safer.
>
> -- Oriol
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Something like Object.freeze, but not inherited from prototypes.

2018-03-24 Thread /#!/JoePea
Currently, `Object.freeze`ing a prototype affects all objects "inheriting"
from the prototype when trying to modify props on an inheriting object when
those same props exist on the prototype, which isn't the behavior that I
want.

I'd like to prevent a prototype from being modifiable directly, but I still
want objects that "inherit" from the prototype to work like normal (i.e.
they can still shadow properties of the prototype and the object will be
modified directly rather than the prototype).

For example, the following is my problem:

```js
prototype.foo = "foo"

Object.freeze( prototype )

const o = Object.create( prototype )

o.foo = "bar" // I want this to work (but it doesn't)

prototype.foo = "baz" // and I want only this to fail because it is
modifying the prototype directly
```

In otherwords, I'd like for inheritance (reading values from the prototype,
and shadowing the prototype) to work like normal, but I don't want someone
to grab the prototype and modify it directly and affect all other instances
of the "class".

Is there some way to do this currently? If not, I'd like to have such a
feature so that only instances of my classes can be modified, but all
prototypes in the inheritance are not.

I'm also noting that Object.seal and Object.preventExtensions behave the
same way (they affect object that inherit from the prototype which is what
I want to avoid).

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Object.unfreeze, or similar API

2018-03-24 Thread /#!/JoePea
Hello Oriol, why did you make two Proxies there? Does it serve some purpose
not achieved with only one Proxy? - Joe

*/#!/*JoePea

On Mon, Feb 19, 2018 at 12:35 PM, Oriol _ <oriol-bugzi...@hotmail.com>
wrote:

> > So, what if there was a way to unfreeze an object in the scope in which
> the object was frozen?
>
> I don't think the behavior of object operations should depend on the scope
> in which they are used.
>
> And I could understand undoing [[PreventExtensions]], just switch
> [[Extensible]] back to true (for ordinary objects). But unfreezing makes no
> sense. How is ES supposed to know which properties became non-configurable
> because of `Object.freeze` and which ones were manually defined as
> non-configurable? Do you want all non-configurable properties to become
> configurable when "unfreezing"? I think that would be bad.
>
> > // recommend all listeners to be synchronous, and not modify the payload
> later
>
> You can recommend, but what if they are not synchronous? They will have a
> reference to the unfrozen object! If you trust them, you can avoid freezing
> in the first place. If you can't trust them, unfreezing is a big problem!
>
> Frankly I don't see the point, if you don't want to clone just use a proxy
> that only allows restricted access.
>
> ```js
> let error = () => { throw new Error(); };
> let allowed = ["get", "ownKeys", "has", "getOwnPropertyDescriptor"];
> let handler = new Proxy(Object.create(null), {
>   get(_, trap, receiver) {
> if (!allowed.includes(trap)) return error;
>   }
> });
> this.emit('some:event', new Proxy(obj, handler));
> ```
>
> -- Oriol
>
> ___
> 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: Object.unfreeze, or similar API

2018-02-19 Thread /#!/JoePea
That's actually very useful, thanks! I have plenty of cases where I wished
I could pass an object without cloning it to ensure it isn't mutated from
outside. And instead of creating the Proxy right when I will emit an event
(for example), I could just store the proxy somewhere so it is long-lived
and to avoid GC.

*/#!/*JoePea

On Mon, Feb 19, 2018 at 12:08 PM, Michał Wadas <michalwa...@gmail.com>
wrote:

> You can just do:
>
> const proxy = new Proxy(obj, {
>set() { throw new Error(); },
>defineProperty() { throw new Error();},
>deleteProperty() { throw new Error(); }
> })
> this.emit('some:event', proxy)
>
>
> Though, it seems like an exotic use case.
>
> On Mon, Feb 19, 2018 at 8:56 PM, /#!/JoePea <j...@trusktr.io> wrote:
>
>> ​
>> I think the ability to unfreeze an object can be useful.
>>
>> For example, suppose we have a library that emits events:
>>
>> ```js
>> this.emit('some:event', this.obj)
>> ```
>>
>> Maybe we want to try to prevent external listeners from modifying the
>> event payload without having to clone `this.obj`, otherwise cloning can
>> cause "jank" from GC during animations that should be smooth.
>>
>> So, what if there was a way to unfreeze an object in the scope in which
>> the object was frozen?
>>
>> ```js
>> Object.freeze(obj) // instead of cloning
>> this.emit('some:event', this.obj) // recommend all listeners to be
>> synchronous, and not modify the payload later
>> Object.unfreeze(this.obj) // in the same scope
>> ```
>>
>> or maybe it return an unfreeze function:
>>
>> ```js
>> const unfreeze = Object.freeze(obj) // instead of cloning
>> this.emit('some:event', this.obj) // recommend all listeners to be
>> synchronous, and not modify the payload later
>> unfreeze(this.obj) // only code that is given the unfreeze function can
>> call it, similar to resolve/reject functions with Promises
>> ```
>>
>> or maybe it is more similar to setTimeout and setInterval:
>>
>> ```js
>> const frozenKey = Object.freeze(obj) // instead of cloning
>> this.emit('some:event', this.obj) // recommend all listeners to be
>> synchronous, and not modify the payload later
>> Object.unfreeze(frozenKey) // only code that is given the key can
>> unfreeze the object associated with the key
>> ```
>>
>> It seems like there can be opportunity for this to be optimized, so that
>> it can be faster than cloning. For example, this uses more memory and
>> causes GC:
>>
>> ```js
>> this.emit('some:event', { ...this.obj }) // creates a new object
>> ```
>>
>> Could the performance benefit make it worth it to have a way to unfreeze
>> objects?
>>
>> Another use case is unlocking things only when used in certain places, as
>> a "guard". In the following example, the only way to set the X rotation
>> value is with the setter, which enforces that certain logic will fire,
>> rather than someone from the outside modifying the readable state not using
>> the setter:
>>
>> ```js
>>
>> import Privates from 'somewhere'
>>
>> // a private cache, using WeakMap internally
>> const _ = new Privates
>>
>> class ThingThatRotates {
>> constructor() {
>> this.rotation = { x: 0, y: 0, z: 0 }
>> _(this).frozen = Object.freeze(this.rotation)
>> // ...
>> }
>>
>> get rotateX() { return this.rotation.x }
>> set rotateX(val) {
>> this.doSomethingImportantWithTheValue(val)
>>
>> // unlock here, so that the value can only be set with this
>> setter.
>> Object.unfreeze(_(this).frozen)
>> this.rotation.x = val
>> _(this).frozen = Object.freeze(this.rotation)
>>
>> this.emitAnEventWithTheValue(val)
>> this.etc(val)
>> }
>>
>> // ...
>> }
>>
>> ```
>>
>> I know, I can probably just keep `rotation` in the private cache, but
>> then it isn't readable. Maybe I want that to be readable as a convenient
>> shortcut. F.e.
>>
>> ```js
>> // outside code
>> const r = new ThingThatRotates
>>
>> // X rotation might be animated by some other tool
>>
>> const {x, y, z} = r.rotation // for convenience, no cloning involved.
>>
>> ```
>>
>> This is a completely contrived example I just made up right now. I can
>> probably think of more. It seems like it could be good for performance in
>> cases where we don't want modification from the outside...
>>
>>
>> /#!/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


Multi-index assignment.

2017-12-04 Thread /#!/JoePea
I always run into situations where I'd like to assign some things from
another array.

For example,

```js
array[0] = 1
array[1] = 2
```

could be written as

```js
array[0, 1] = [1, 2]
```

and maybe perhaps also specific access on the right hand side too:

```js
array[1] = otherArray[3]
array[4] = otherArray[5]
// can be
array[
​1​
,
​4​
] = [
​
otherArray[3]
​
,
​
otherArray[
​5​
]
​
]
​// but also a shorter form:

array[1, 4] = otherArray[3, 5]
```

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Cancel Promise pattern (no cancellable promises)

2017-11-29 Thread /#!/JoePea
Hello all, I'm posting here because I'm thinking about how not to leak
memory, and wondering if I am.

Suppose I have an object that is cleaned up (GC'd), and that object's
constructor (for example) ran an anonymous function that listened to a
Promise. For exampel:

```js
class Foo {
  constructor() {
// ...
this.somePromise.then(() => {console.log('this will never fire if this
object is GC'd')})
  }
}
```

Suppose that if this object gets collected, then it means that there is
nothing in my application that will ever be able to resolve this object's
`somePromise`.

Does the engine also garbage collect `somePromise` and the attached handler?

Now, what if `somePromise` is referenced outside of this object by some
other code waiting on yet another promise who's handler will resolve this
object's `somePromise`? Does this prevent the object from being GC'd? Or is
the object GC'd, but `somePromise` is not and the above console.log should
still fire at some point (or memory will be leaked)?


*/#!/*JoePea

On Thu, Jan 12, 2017 at 1:12 PM, Isiah Meadows <isiahmead...@gmail.com>
wrote:

> And that's why we're waiting on the next meeting to happen with notes
> posted, so we can figure out what to do next. It's likely to get discussed,
> especially considering the current situation and pressing need for it.
>
> On Thu, Jan 12, 2017, 13:27 Jordan Harband <ljh...@gmail.com> wrote:
>
>> The Cancellable Promises proposal itself is currently withdrawn, but
>> don't forget that all of the previous discussion on cancellation in
>> promises led to that proposal.
>>
>> It would be shortsighted to pretend they don't exist, or that the spec
>> proposal won't matter forever to any other cancellation proposal, and doing
>> so won't help any alternative proposal.
>>
>> On Thu, Jan 12, 2017 at 7:44 AM, Jan-Ivar Bruaroey <j...@mozilla.com>
>> wrote:
>>
>> Cancellable promises is dead. Please don't hijack this thread discussing
>> them.
>>
>> Thanks,
>>
>> .: Jan-Ivar :.
>>
>>
>> ___
>> 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
>>
>
> ___
> 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: Touch/Trackpad finger position

2017-11-07 Thread /#!/JoePea
The best place to ask about this is probably somewhere here:
github.com/whatwg. I'm not sure which repo this topic would be in, but you
can kindly ask about which repo to post in once you've opened an issue in
the repo you think is most related. My guess would be github.com/whatwg/dom.

*/#!/*JoePea

On Tue, Nov 7, 2017 at 4:37 PM, Isiah Meadows <isiahmead...@gmail.com>
wrote:

> Also, for future reference, these kinds of feature requests belong in the
> WHATWG's mailing lists, not here.
>
> On Tue, Nov 7, 2017, 18:59 Eli Perelman <e...@eliperelman.com> wrote:
>
>> The ECMAScript language deals with semantics around the specific
>> programming language, while native interactions are supplied by the host
>> environment, e.g. Node.js and the browser. This is why interactions like
>> window and document events are defined by W3C and friends, and
>> strictly-language items are handled by ES.
>>
>> You'll probably want something like Touch Events, defined by the host
>> environment:
>>
>> https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
>>
>> On Tue, Nov 7, 2017 at 5:53 PM Felipe Nascimento de Moura <
>> felipenmo...@gmail.com> wrote:
>>
>>> Hi.
>>> If I'm being too crazy here, please let me know!
>>>
>>> What would it require for us to have an API to get the exact position of
>>> fingers/touches from the trackpad? (even it not pressed)
>>>
>>> For example, let's say someone wants to write a WebApp in which you
>>> could sign something, or simply use a (good) handwriting feature instead of
>>> pressing/clicking.
>>>
>>> This is a feature that is supported for native apps...
>>> I wonder why it shouldn't be supported for the web :)
>>>
>>> [ ]s
>>>
>>> *--*
>>>
>>> *Felipe N. Moura*
>>> Web Developer, Google Developer Expert
>>> <https://developers.google.com/experts/people/felipe-moura>, Founder of
>>> BrazilJS <https://braziljs.org/> and Nasc <http://nasc.io/>.
>>>
>>> Website:  http://felipenmoura.com / http://nasc.io/
>>> Twitter:@felipenmoura <http://twitter.com/felipenmoura>
>>> Facebook: http://fb.com/felipenmoura
>>> LinkedIn: http://goo.gl/qGmq
>>> -
>>> *Changing  the  world*  is the least I expect from  myself!
>>> ___
>>> 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
>>
>
> ___
> 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: Compiled JS

2017-10-24 Thread /#!/JoePea
What do you mean? Like coffeescript?

*/#!/*JoePea

On Tue, Oct 24, 2017 at 2:06 PM, doodad-js Admin <dooda...@gmail.com> wrote:

> Hi,
>
>
>
> By seeing many proposals about reducing the syntax for X and Y, I just
> want to open the idea of a [non-native] compiled JS world. What do you
> think?
>
>
>
> Because, if that’s not the problem (code size), what it is ?
>
>
>
> Claude Petit
>
>
>
>
> <http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=emailclient>
>  Virus-free.
> www.avg.com
> <http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=emailclient>
> <#m_-232428727760528994_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>
> ___
> 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: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
I'm not polyfilling Custom Elements, I'm polyfilling something else
that doesn't have the problems that Custom Elements has that makes
them not usable with SVG.
/#!/JoePea


On Tue, Oct 24, 2017 at 12:42 PM, Boris Zbarsky <bzbar...@mit.edu> wrote:
> On 10/24/17 2:03 PM, /#!/JoePea wrote:
>>
>> I was trying to patch `Element` because there's also `SVGElement`
>
>
> For what it's worth, looks like for the moment custom elements has given up
> on the idea of custom non-HTML elements...
>
> -Boris
>
> ___
> 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: Object method shorthand after initial declaration

2017-10-24 Thread /#!/JoePea
`obj.foo() {}` is a syntax error in Chrome, so it seems possible to
make that a function definition.
/#!/JoePea


On Tue, Oct 24, 2017 at 12:45 PM, Brian Blakely
<anewpage.me...@gmail.com> wrote:
> Is it only valid with a semicolon after `foo()`, though?  Pragma without
> semicolon throws in three engines.
>
> On Tue, Oct 24, 2017 at 2:41 PM, James Kyle <m...@thejameskyle.com> wrote:
>>
>> To parse it that way would be changing behavior.
>>
>> obj.foo() {}
>> this.bar() {}
>>
>> Are both call expressions followed by a block. They are valid syntaxes
>> today.
>>
>> Think:
>>
>> obj.foo();
>> {
>> let a = 1;
>> }
>>
>>
>> On Wed, 25 Oct 2017 at 4:29 am, Brian Blakely <anewpage.me...@gmail.com>
>> wrote:
>>>
>>> Extend the method shorthand syntax beyond initial object declaration.
>>>
>>> ```js
>>> const obj = {};
>>>
>>> obj.foo() {...}
>>> ```
>>>
>>> Equivalent 2015 syntax:
>>>
>>> ```js
>>> const obj = {
>>>   foo() {...}
>>> };
>>> ```
>>>
>>> This is nice for assignment to context:
>>>
>>> ```js
>>> function Foo() {
>>>   this.bar() {...}
>>>   this.baz() {...}
>>> }
>>>
>>> const foo = new Foo();
>>> foo.bar();
>>> foo.baz();
>>> ```
>>>
>>> Equivalent 2015 syntax:
>>>
>>> ```js
>>> function Foo() {
>>>   this.bar = function() {...};
>>>   this.baz = function() {...};
>>> }
>>> ```
>>> ___
>>> 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Shorter syntax for arrow function assignment

2017-10-24 Thread /#!/JoePea
It doesn't matter if `function`s are being used less, they simply
aren't going away. There's plenty of people specifically relying on
`function` for certain purposes where arrow functions do not work.
Lets avoid getting arrows confused with functions.

```js
const prototype = /* ... get this prototype object from somewhere ... */

prototype.foo = function foo() {
  // do something with `this`.
}
```

That sort of stuff (relying on non-arrows) isn't going away.
/#!/JoePea


On Tue, Oct 24, 2017 at 1:12 PM, Brian Blakely <anewpage.me...@gmail.com> wrote:
> To be clear, this isn't a proposal to drop support for something.  Don't
> optimize for a fading use-case, however.
>
>>it doesn't seem to add anything other than "I don't like typing '='".
>
> That is absolutely correct, it is a proposal for shorthand syntax.
>
>
> On Tue, Oct 24, 2017 at 4:08 PM, dante federici <c.dante.feder...@gmail.com>
> wrote:
>>
>> The use case fading away doesn't mean you can drop support for it, or that
>> it won't still be in use.
>>
>> Please stop trying to push your "shorthand" syntax of:
>> ```
>> myFn() {
>> }
>> ```
>>
>> It's already been pointed out in multiple cases that:
>> 1. The current usages are not "outmoded"
>> 2. The proposed syntax has misleading `this` binding without the arrow
>> 3. Blocks, ASI, and the object shorthand notation either conflict or make
>> it vague how to interpret
>>
>> This isn't a beneficial syntax moving forward, and it doesn't seem to add
>> anything other than "I don't like typing '='".
>>
>> ___
>> 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
It's a generic thing to forever impact all future descendants of
Element, in theory. For example, a feature like "Element Behaviors" as
[described here](https://github.com/w3c/webcomponents/issues/662) (but
I'm going to close that one and open a more concise issue with a
working implementation).

The idea is that it would work on any type of element because it is
really generic (just like jQuery works on any type of element), so
patching Element seemed the best way to do it.
/#!/JoePea


On Tue, Oct 24, 2017 at 11:36 AM, Andrea Giammarchi
<andrea.giammar...@gmail.com> wrote:
> are you patching things you know need patching or you want to pollute
> forever the future with your patch?
> Whatever you are doing should not compromise WebGLElement so it's good you
> are unable to patch Element, IMO
>
> On Tue, Oct 24, 2017 at 3:03 PM, /#!/JoePea <j...@trusktr.io> wrote:
>>
>> I'm going to use the accessor technique as it's the only way. Thanks!
>>
>> I was trying to patch `Element` because there's also `SVGElement`. I
>> suppose I can duplicate efforts and patch both `HTMLElement` and
>> `SVGElement`; that's not too difficult, but it is conceptually uglier
>> because for example, what if browsers come out with `MathElement`,
>> `WebGLElement`, etc.
>> /#!/JoePea
>>
>>
>> On Tue, Oct 24, 2017 at 10:55 AM, Michał Wadas <michalwa...@gmail.com>
>> wrote:
>> >> To "polyfill" an idea I have for DOM, to propose it later, etc.
>> >
>> > You can consider something like this depending on your needs:
>> > https://gist.github.com/Ginden/03004e52b3d331e236b5256e3b4c08ff
>> >
>> > On Tue, Oct 24, 2017 at 7:47 PM, /#!/JoePea <j...@trusktr.io> wrote:
>> >>
>> >> @Michał
>> >>
>> >> > But why do you need this?
>> >>
>> >> To "polyfill" an idea I have for DOM, to propose it later, etc.
>> >>
>> >> @Logan
>> >>
>> >> > Why not store your data separately in a WeakMap and rather than
>> >> > injecting properties onto existing objects? Then you can initialize
>> >> > the
>> >> > stored data on first access of the data you want.
>> >>
>> >> I thought about that, it seems like the only way, but was curious to
>> >> see about the the during-construction way if possible.
>> >>
>> >> @Andrea
>> >>
>> >> But this one doesn't work:
>> >>
>> >> ```js
>> >> window.Element = class extends Element {
>> >>   constructor() {
>> >> super();
>> >> console.log('hello darkness my old friend');
>> >>   }
>> >> };
>> >>
>> >> // then ...
>> >> class MyEl extends HTMLElement {}
>> >> customElements.define('my-el', MyEl);
>> >>
>> >> new MyEl;
>> >> ```
>> >>
>> >> /#!/JoePea
>> >>
>> >>
>> >> On Tue, Oct 24, 2017 at 10:36 AM, Andrea Giammarchi
>> >> <andrea.giammar...@gmail.com> wrote:
>> >> > I know I'm going to regret this already, but since I've secretly
>> >> > played
>> >> > with
>> >> > polyfills, you can still do this:
>> >> >
>> >> > ```js
>> >> > window.HTMLElement = class extends HTMLElement {
>> >> >   constructor() {
>> >> > super();
>> >> > console.log('hello darkness my old friend');
>> >> >   }
>> >> > };
>> >> >
>> >> > // then ...
>> >> > class MyEl extends HTMLElement {}
>> >> > customElements.define('my-el', MyEl);
>> >> >
>> >> > new MyEl;
>> >> > ```
>> >> >
>> >> > Regards
>> >> >
>> >> >
>> >> >
>> >> > On Tue, Oct 24, 2017 at 2:32 PM, Logan Smyth <loganfsm...@gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Given that these are constructors that you don't own, adding your
>> >> >> own
>> >> >> properties to them seems like an overall ugly approach to me. Why
>> >> >> not
>> >> >> store
>> >> >> your data separately in a WeakMap and rather than injecting
>> >> >> properties
>> >> >> onto
>> >> >> existing objects? Then you can initialize the st

Are Map with no references and their values with no references GC'd?

2017-10-24 Thread /#!/JoePea
I have a `WeakMap` whose values are `Map` instances. The values of all
the `Map`s inside the `WeakMap` are `object`s. If references to keys
of the `WeakMap` are lost and therefore those items removed from the
`WeakMap`, will the `Map`s' values be GC'd if there are no references
to the Maps or to the Map values.

I'm intuitively assuming "yes", but just want to confirm that I don't
have to explicitly removed everything from the `Map`s manually first.

/#!/JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
I'm going to use the accessor technique as it's the only way. Thanks!

I was trying to patch `Element` because there's also `SVGElement`. I
suppose I can duplicate efforts and patch both `HTMLElement` and
`SVGElement`; that's not too difficult, but it is conceptually uglier
because for example, what if browsers come out with `MathElement`,
`WebGLElement`, etc.
/#!/JoePea


On Tue, Oct 24, 2017 at 10:55 AM, Michał Wadas <michalwa...@gmail.com> wrote:
>> To "polyfill" an idea I have for DOM, to propose it later, etc.
>
> You can consider something like this depending on your needs:
> https://gist.github.com/Ginden/03004e52b3d331e236b5256e3b4c08ff
>
> On Tue, Oct 24, 2017 at 7:47 PM, /#!/JoePea <j...@trusktr.io> wrote:
>>
>> @Michał
>>
>> > But why do you need this?
>>
>> To "polyfill" an idea I have for DOM, to propose it later, etc.
>>
>> @Logan
>>
>> > Why not store your data separately in a WeakMap and rather than
>> > injecting properties onto existing objects? Then you can initialize the
>> > stored data on first access of the data you want.
>>
>> I thought about that, it seems like the only way, but was curious to
>> see about the the during-construction way if possible.
>>
>> @Andrea
>>
>> But this one doesn't work:
>>
>> ```js
>> window.Element = class extends Element {
>>   constructor() {
>> super();
>> console.log('hello darkness my old friend');
>>   }
>> };
>>
>> // then ...
>> class MyEl extends HTMLElement {}
>> customElements.define('my-el', MyEl);
>>
>> new MyEl;
>> ```
>>
>> /#!/JoePea
>>
>>
>> On Tue, Oct 24, 2017 at 10:36 AM, Andrea Giammarchi
>> <andrea.giammar...@gmail.com> wrote:
>> > I know I'm going to regret this already, but since I've secretly played
>> > with
>> > polyfills, you can still do this:
>> >
>> > ```js
>> > window.HTMLElement = class extends HTMLElement {
>> >   constructor() {
>> > super();
>> > console.log('hello darkness my old friend');
>> >   }
>> > };
>> >
>> > // then ...
>> > class MyEl extends HTMLElement {}
>> > customElements.define('my-el', MyEl);
>> >
>> > new MyEl;
>> > ```
>> >
>> > Regards
>> >
>> >
>> >
>> > On Tue, Oct 24, 2017 at 2:32 PM, Logan Smyth <loganfsm...@gmail.com>
>> > wrote:
>> >>
>> >> Given that these are constructors that you don't own, adding your own
>> >> properties to them seems like an overall ugly approach to me. Why not
>> >> store
>> >> your data separately in a WeakMap and rather than injecting properties
>> >> onto
>> >> existing objects? Then you can initialize the stored data on first
>> >> access of
>> >> the data you want.
>> >>
>> >> On Tue, Oct 24, 2017 at 10:25 AM, /#!/JoePea <j...@trusktr.io> wrote:
>> >>>
>> >>> Well, I know I can set accessors on a prototype easily, but what I
>> >>> mean is, I need each instance of an `Element` to have exactly one
>> >>> instance of something right after construction during the same
>> >>> synchronous operation.
>> >>>
>> >>> For example, if we have an application with a bunch of pre-existing
>> >>> Elements that do not extend from any classes of mine, I'd like for the
>> >>> all to have `foo` properties, so that I can do this:
>> >>>
>> >>> ```js
>> >>> const el = new SomeCustomElementThatWasDefinedCreatedByMe
>> >>> console.log(el.foo) // it exists and is specific to the instance, not
>> >>> a prototype property
>> >>>
>> >>> // or
>> >>>
>> >>> const div = document.createElement('div')
>> >>> console.log(div.foo) // it exists and is specific to the instance, not
>> >>> a prototype property
>> >>> ```
>> >>>
>> >>> Can this be done?
>> >>> /#!/JoePea
>> >>>
>> >>>
>> >>> On Tue, Oct 24, 2017 at 10:19 AM, /#!/JoePea <j...@trusktr.io> wrote:
>> >>> >> This feels like a problem similar to
>> >>> >> https://esdiscuss.org/topic/block-scoped-prototype-extensions
>> >>> >
>> >>> > @Boris, even if it were scoped, how d

Re: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
@Michał

> But why do you need this?

To "polyfill" an idea I have for DOM, to propose it later, etc.

@Logan

> Why not store your data separately in a WeakMap and rather than injecting 
> properties onto existing objects? Then you can initialize the stored data on 
> first access of the data you want.

I thought about that, it seems like the only way, but was curious to
see about the the during-construction way if possible.

@Andrea

But this one doesn't work:

```js
window.Element = class extends Element {
  constructor() {
super();
console.log('hello darkness my old friend');
  }
};

// then ...
class MyEl extends HTMLElement {}
customElements.define('my-el', MyEl);

new MyEl;
```

/#!/JoePea


On Tue, Oct 24, 2017 at 10:36 AM, Andrea Giammarchi
<andrea.giammar...@gmail.com> wrote:
> I know I'm going to regret this already, but since I've secretly played with
> polyfills, you can still do this:
>
> ```js
> window.HTMLElement = class extends HTMLElement {
>   constructor() {
> super();
> console.log('hello darkness my old friend');
>   }
> };
>
> // then ...
> class MyEl extends HTMLElement {}
> customElements.define('my-el', MyEl);
>
> new MyEl;
> ```
>
> Regards
>
>
>
> On Tue, Oct 24, 2017 at 2:32 PM, Logan Smyth <loganfsm...@gmail.com> wrote:
>>
>> Given that these are constructors that you don't own, adding your own
>> properties to them seems like an overall ugly approach to me. Why not store
>> your data separately in a WeakMap and rather than injecting properties onto
>> existing objects? Then you can initialize the stored data on first access of
>> the data you want.
>>
>> On Tue, Oct 24, 2017 at 10:25 AM, /#!/JoePea <j...@trusktr.io> wrote:
>>>
>>> Well, I know I can set accessors on a prototype easily, but what I
>>> mean is, I need each instance of an `Element` to have exactly one
>>> instance of something right after construction during the same
>>> synchronous operation.
>>>
>>> For example, if we have an application with a bunch of pre-existing
>>> Elements that do not extend from any classes of mine, I'd like for the
>>> all to have `foo` properties, so that I can do this:
>>>
>>> ```js
>>> const el = new SomeCustomElementThatWasDefinedCreatedByMe
>>> console.log(el.foo) // it exists and is specific to the instance, not
>>> a prototype property
>>>
>>> // or
>>>
>>> const div = document.createElement('div')
>>> console.log(div.foo) // it exists and is specific to the instance, not
>>> a prototype property
>>> ```
>>>
>>> Can this be done?
>>> /#!/JoePea
>>>
>>>
>>> On Tue, Oct 24, 2017 at 10:19 AM, /#!/JoePea <j...@trusktr.io> wrote:
>>> >> This feels like a problem similar to
>>> >> https://esdiscuss.org/topic/block-scoped-prototype-extensions
>>> >
>>> > @Boris, even if it were scoped, how do we monkey patch a
>>> > *constructor*? By the way, for some reason your link to
>>> > `https://esdiscuss.org/topic/block-scoped-prototype-extensions` posted
>>> > as `https://esdiscuss.org/topic/block` which is 404. If you can edit
>>> > it it would help others not to stumble on a broken link.
>>> >
>>> >> if that would be possible, then everyone could just monkey patch
>>> >> Object, right?
>>> >
>>> > But everyone can monkey patch the entire class already, aside from the
>>> > constructor, by modifying the prototype. Obviously if someone returns
>>> > something new from the constructor they might break everything, but it
>>> > will be completely obvious and people then won't do that. The same
>>> > applies with methods and properties, it is super easy to break entire
>>> > applications monkey patching methods.
>>> >
>>> > ---
>>> >
>>> > So suppose I want to "polyfill" a concept. For example, I want all
>>> > elements to have a new "foo" accessor after they've been constructed.
>>> > Or for example, suppose `HTMLElement.prototype.style` and
>>> > `SVGElement.prototype.style` didn't exist yet. How would I patch those
>>> > in?
>>> > /#!/JoePea
>>> >
>>> >
>>> > On Tue, Oct 24, 2017 at 10:07 AM, Michał Wadas <michalwa...@gmail.com>
>>> > wrote:
>>> >> AFAIR DOM classes are not extensible by any means.
>>> >>
>>> >>
>>> >>

Re: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
Well, I know I can set accessors on a prototype easily, but what I
mean is, I need each instance of an `Element` to have exactly one
instance of something right after construction during the same
synchronous operation.

For example, if we have an application with a bunch of pre-existing
Elements that do not extend from any classes of mine, I'd like for the
all to have `foo` properties, so that I can do this:

```js
const el = new SomeCustomElementThatWasDefinedCreatedByMe
console.log(el.foo) // it exists and is specific to the instance, not
a prototype property

// or

const div = document.createElement('div')
console.log(div.foo) // it exists and is specific to the instance, not
a prototype property
```

Can this be done?
/#!/JoePea


On Tue, Oct 24, 2017 at 10:19 AM, /#!/JoePea <j...@trusktr.io> wrote:
>> This feels like a problem similar to 
>> https://esdiscuss.org/topic/block-scoped-prototype-extensions
>
> @Boris, even if it were scoped, how do we monkey patch a
> *constructor*? By the way, for some reason your link to
> `https://esdiscuss.org/topic/block-scoped-prototype-extensions` posted
> as `https://esdiscuss.org/topic/block` which is 404. If you can edit
> it it would help others not to stumble on a broken link.
>
>> if that would be possible, then everyone could just monkey patch Object, 
>> right?
>
> But everyone can monkey patch the entire class already, aside from the
> constructor, by modifying the prototype. Obviously if someone returns
> something new from the constructor they might break everything, but it
> will be completely obvious and people then won't do that. The same
> applies with methods and properties, it is super easy to break entire
> applications monkey patching methods.
>
> ---
>
> So suppose I want to "polyfill" a concept. For example, I want all
> elements to have a new "foo" accessor after they've been constructed.
> Or for example, suppose `HTMLElement.prototype.style` and
> `SVGElement.prototype.style` didn't exist yet. How would I patch those
> in?
> /#!/JoePea
>
>
> On Tue, Oct 24, 2017 at 10:07 AM, Michał Wadas <michalwa...@gmail.com> wrote:
>> AFAIR DOM classes are not extensible by any means.
>>
>>
>>
>> On 24 Oct 2017 6:51 pm, "/#!/JoePea" <j...@trusktr.io> wrote:
>>>
>>> Is it possible to monkey-patch an intermediate constructor of a built-in
>>> subclass?
>>>
>>> For example, suppose I want all `Element` instances in a web app to have
>>> new instance properties, is there a way to monkey-patch the Element
>>> constructor so that when I make a custom element by extending a subclass of
>>> `Element` that the new logic will fire?
>>>
>>> For example:
>>>
>>> ```js
>>> // monkey-patch the Element constructor somehow so that it logs "patched
>>> in Element".
>>>
>>> // then
>>> class FooBar extends HTMLElement {}
>>> customElement.define('foo-bar', FooBar)
>>> new FooBar // "patched in Element"
>>> ```
>>>
>>> I tried
>>>
>>> ```js
>>> const OldElement = window.Element
>>>
>>> window.Element = function Element() {
>>>   const _this = new OldElement
>>>   console.log("patched in Element")
>>>   return _this
>>> }
>>>
>>> window.Element.prototype = OldElement.prototype
>>> window.Element.prototype.constructor = window.Element
>>>
>>> class FooBar extends HTMLElement {}
>>> customElements.define('f-b', FooBar)
>>> new FooBar // does not log "patched in Element"
>>> ```
>>>
>>> But when I make a new custom element, constructing it seems to use the old
>>> Element constructor, as if a non-global reference to the original
>>> constructor is kept inside a module so that modifying the global wouldn't
>>> have any effect.
>>>
>>> Is there a way to monkey patch a constructor in the middle of a built-in
>>> prototype chain or to otherwise inject construction logic to base classes of
>>> existing class hierarchies?
>>>
>>>
>>> /#!/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: Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
> This feels like a problem similar to 
> https://esdiscuss.org/topic/block-scoped-prototype-extensions

@Boris, even if it were scoped, how do we monkey patch a
*constructor*? By the way, for some reason your link to
`https://esdiscuss.org/topic/block-scoped-prototype-extensions` posted
as `https://esdiscuss.org/topic/block` which is 404. If you can edit
it it would help others not to stumble on a broken link.

> if that would be possible, then everyone could just monkey patch Object, 
> right?

But everyone can monkey patch the entire class already, aside from the
constructor, by modifying the prototype. Obviously if someone returns
something new from the constructor they might break everything, but it
will be completely obvious and people then won't do that. The same
applies with methods and properties, it is super easy to break entire
applications monkey patching methods.

---

So suppose I want to "polyfill" a concept. For example, I want all
elements to have a new "foo" accessor after they've been constructed.
Or for example, suppose `HTMLElement.prototype.style` and
`SVGElement.prototype.style` didn't exist yet. How would I patch those
in?
/#!/JoePea


On Tue, Oct 24, 2017 at 10:07 AM, Michał Wadas <michalwa...@gmail.com> wrote:
> AFAIR DOM classes are not extensible by any means.
>
>
>
> On 24 Oct 2017 6:51 pm, "/#!/JoePea" <j...@trusktr.io> wrote:
>>
>> Is it possible to monkey-patch an intermediate constructor of a built-in
>> subclass?
>>
>> For example, suppose I want all `Element` instances in a web app to have
>> new instance properties, is there a way to monkey-patch the Element
>> constructor so that when I make a custom element by extending a subclass of
>> `Element` that the new logic will fire?
>>
>> For example:
>>
>> ```js
>> // monkey-patch the Element constructor somehow so that it logs "patched
>> in Element".
>>
>> // then
>> class FooBar extends HTMLElement {}
>> customElement.define('foo-bar', FooBar)
>> new FooBar // "patched in Element"
>> ```
>>
>> I tried
>>
>> ```js
>> const OldElement = window.Element
>>
>> window.Element = function Element() {
>>   const _this = new OldElement
>>   console.log("patched in Element")
>>   return _this
>> }
>>
>> window.Element.prototype = OldElement.prototype
>> window.Element.prototype.constructor = window.Element
>>
>> class FooBar extends HTMLElement {}
>> customElements.define('f-b', FooBar)
>> new FooBar // does not log "patched in Element"
>> ```
>>
>> But when I make a new custom element, constructing it seems to use the old
>> Element constructor, as if a non-global reference to the original
>> constructor is kept inside a module so that modifying the global wouldn't
>> have any effect.
>>
>> Is there a way to monkey patch a constructor in the middle of a built-in
>> prototype chain or to otherwise inject construction logic to base classes of
>> existing class hierarchies?
>>
>>
>> /#!/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: Shorter syntax for arrow function assignment

2017-10-24 Thread /#!/JoePea
It can be confusing because it is too similar to non-arrow functions. The
arrow syntax is clear in meaning.

*/#!/*JoePea

On Tue, Oct 24, 2017 at 9:51 AM, Brian Blakely <anewpage.me...@gmail.com>
wrote:

> This syntax is shorter, easier to write, and arguably easier to read.
> What else does it need to offer?
>
> On Tue, Oct 24, 2017 at 12:48 PM, kai zhu <kaizhu...@gmail.com> wrote:
>
>> -1
>> this fails styleguide sanity-check.
>>
>> we currently have 3 common styles of declaring functions:
>> 1. foo = function () {...}
>> 2. function foo () {...}
>> 3. foo = () => {...}
>>
>> does this extra 4th style offer anything new to justify making the
>> javascript language even less consistent than it already is?  i say
>> no.
>>
>>
>> On 10/25/17, Brian Blakely <anewpage.me...@gmail.com> wrote:
>> > A prevalent pattern has emerged:
>> >
>> > `export const foo = ()=> { };`
>> >
>> > Taking a cue from short method syntax, this comes to mind as a possible
>> > improvement:
>> >
>> > `export const foo() { };`
>> >
>> > Even better if we assume const:
>> >
>> > `export foo() { };`
>> >
>> > That is delicious.  Thoughts?
>> >
>>
>
>
> ___
> 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


Monkey patching constructors in builtin class hierarchies?

2017-10-24 Thread /#!/JoePea
Is it possible to monkey-patch an intermediate constructor of a built-in
subclass?

For example, suppose I want all `Element` instances in a web app to have
new instance properties, is there a way to monkey-patch the Element
constructor so that when I make a custom element by extending a subclass of
`Element` that the new logic will fire?

For example:

```js
// monkey-patch the Element constructor somehow so that it logs "patched in
Element".

// then
class FooBar extends HTMLElement {}
customElement.define('foo-bar', FooBar)
new FooBar // "patched in Element"
```

I tried

```js
const OldElement = window.Element

window.Element = function Element() {
  const _this = new OldElement
  console.log("patched in Element")
  return _this
}

window.Element.prototype = OldElement.prototype
window.Element.prototype.constructor = window.Element

class FooBar extends HTMLElement {}
customElements.define('f-b', FooBar)
new FooBar // does not log "patched in Element"
```

But when I make a new custom element, constructing it seems to use the old
Element constructor, as if a non-global reference to the original
constructor is kept inside a module so that modifying the global wouldn't
have any effect.

Is there a way to monkey patch a constructor in the middle of a built-in
prototype chain or to otherwise inject construction logic to base classes
of existing class hierarchies?


*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The `super` keyword doesn't work as it should?

2017-10-21 Thread /#!/JoePea
Here's a new real-world example showing people are naturally expecting ES6
`super` to be dynamic when they copy methods from objects to other objects:
https://stackoverflow.com/questions/46306598.

It makes sense to assume it would work this way considering how dynamic
pre-ES6 is!

*/#!/*JoePea

On Mon, Aug 1, 2016 at 11:11 PM, /#!/JoePea <j...@trusktr.io> wrote:

> Alan, after considering the [March 25th Declarative Alternative to
> toMethod conversation](https://github.com/tc39/tc39-notes/blob/
> master/es6/2015-03/mar-25.md#6iv-a-declarative-alternative-
> to-tomethod-allen-wirfs-brock), it really seems like a dynamic `super`
> would solve the problems mentioned. The extra syntaxes,
>
> ```js
> let mixins = obj => obj mixin {...}; mixins(target);
> mixin TextSupport {...}
> class MyComponent extends EmberComponent with TextSupport {...}
> function (super) foo (x, y) { ...super ...x ...y }
> //etc
> ```
>
> just seem like ways to work around the static `super` problem, introduce a
> bunch of new syntax when it is completely not needed, and as mentioned in
> that conversation:
>
> > YK: want to avoid "harsh end of life" outcome for ES5-ish libraries.
>
> which depicts the very fragmentation between ES5 and ES6 that I mentioned
> previously, which will cause a paradigm fork where some libraries will be
> targeted at ES5 features or ES6 features but not both when ideally the
> libraries should work with both feature sets. It would be great for the
> progress of the JavaScript language to be linear rather than forked (f.e.
> concise methods and class methods should be just functions with dynamic
> `super`s that can be manipulated just as we're used to in the pre-ES6 era).
>
> If `super` were dynamic, then users of widely-adopted libraries like
> Backbone would have huge benefits:
>
> ```js
> let NewClass = SomeBackboneClass.extend({
>   someMethod() {
> // ...
> super.someMethod() // this would work!! It would be awesome for
> existing code bases!!
>   }
> })
> ```
>
> That will currently fail for the same reason as why `Object.assign` fails:
> because `HomeObject` is static.
>
> Would you or someone please convince me that a dynamic `super` would be
> overhead-costly and performance-killing enough to have it be static?
>
> */#!/*JoePea
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Why are object initializer methods not usable as constructors?

2017-05-15 Thread /#!/JoePea
> Because they're methods, not functions. The distinction between the
> two was merely semantic in ES5, but now it's mechanical, due to
> super(); constructing something intended as a method would make
> super() behave in confusing and unintuitive ways, so methods just
> don't have a constructor any more.

You are correct for app authors, but wrong for library authors. A
library author may easily like to make an object that contains ES5
constructors, and writing them like

```
let ctors = {
  Foo() {},
  Bar() {},
}
```

is simply simple.

For example, suppose a library author releases a `Class` function for
defining classes, it could be used like this:

```
const Animal = Class({
  constructor: function() {
console.log('new Animal')
  }
})
```

but most JS authors who don't know about these pesky new JavaScript
language internals might be inclined to write:


```
const Animal = Class({
  constructor() {
console.log('new Animal')
  }
})
```

If the `Class` implementation returns that "constructor", then when
the user does `new Animal` they will get an unexpected error, and that
is not ideal at all for a dynamic language like JavaScript.

What's even stranger is that the `Class` implementation can wrap the
concise method with a [[Construct]]able function and call the concise
method with `.call` or `.apply` and it will work! But that is simply
just messy and ugly.

So why prevent it from working only sometimes? It would be much better
for it to just work all the time, and make restrictions only when
`super` is present in the function body. In the above example, the
`constructor() {}` concise method does not use the keyword `super`, so
treating it like `constructor: function constructor() {}` would be
much more ideal.

We shouldn't limit developer creativity for reasons that don't exist
(I haven't heard of any compelling reasons so far).

The new language features cause failures in unexpected ways, and I
really don't think the language should be designed in this
less-intuitive way.

JavaScript pre-ES6 has a dynamic nature, but ES6 and newer features
are less-so in that tradition.

> Making this one niche use-case ("I want to define several constructor-only 
> classes inline in an object initializer") require a few characters less is 
> not a sufficiently worthwhile benefit for the cost.

Actually, no, I want to allow end-users of my library to pass in
objects containing methods and properties, and I don't want the result
to fail in unexpected ways, and I also don't want to write ugly and
hacky code to make it work.

> Just type the few extra characters (exactly what you would have typed in ES5, 
> so it's not even a new imposition), and you'll be fine.

Like I said, it won't be me typing these things, it will be end users.
Yes I can disguise the problem, but if I for example were implementing
a `Class` tool, I wouldn't like to wrap their non-constructable
methods in a proxy function just to make it work not only because it
is ugly, but because it will show things in the console that are more
difficult to debug.

For example, have you ever looked at classes made with Backbone? They
are not so nice to inspect because Backbone wraps constructors and
prototypes like an onion.

This language "feature" of concise methods that makes them not
constructable forces library authors to write ugly code who's output
is harder to inspect and debug by end developers.
/#!/JoePea


On Sat, Jul 30, 2016 at 3:04 AM, /#!/JoePea <j...@trusktr.io> wrote:
>>  The distinction between the two was merely semantic in ES5, but now it's
>> mechanical, due to super(); constructing something intended as a method
>> would make super() behave in confusing and unintuitive ways, so methods just
>> don't have a constructor any more.
>
> So, if `super` were dynamic, then it would be no problem.
>
>> It's been explained to you already in previous threads why super() is
>> designed the way it is, and how a dynamic super() would add significant cost
>> to some situations
>
> Those "some situations" haven't been listed yet (or I don't know where they
> are listed). Do you know any? As far as I can tell, a dynamic super would
> perform just fine:
>
> - For constructor calls, `HomeObject` can just the `.prototype` property of
> the function when `new.target` is the same as the function being
> constructed. That's simple.
> - If `new.target` is not the current constructed function, then the current
> function was found on the prototype chain of
> `Object.getPrototypeOf(new.target)` (i.e. tje `.constructor` property was
> found on some `HomeObject` in the prototype chain) and then that function is
> called with the found `HomeObject`. This seems like a simple addition to the
> property lookup algorithm.
> - Functions called as methods simply have `HomeObject` passed as the
&

  1   2   3   >