<div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000">I forgot to add, this even works with builtin scenarios like Custom Elements,</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000">```js</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000">class MyEl extends mix(HTMLButtonElement, One, Two, Three) { /* ... */ }</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000">customElements.define('my-el', MyEl)</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:#000000">```</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 22, 2019 at 9:36 AM #!/JoePea <<a href="mailto:joe@trusktr.io">joe@trusktr.io</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">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.</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">For example, here's a boilerplate-heavy mixin of mine: </div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">- Header: <a href="https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L55" style="font-family:Arial,Helvetica,sans-serif" target="_blank">https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L55</a></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">- Footer: <a href="https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L615" style="font-family:Arial,Helvetica,sans-serif" target="_blank">https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L615</a></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">- Mixin helper application (provides mixin result caching, deduplication, Symbol.hasInstance, etc): <a href="https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L662" style="font-family:Arial,Helvetica,sans-serif" target="_blank">https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L662</a></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">- The type system that I imported from my lowclass lib: <a href="https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L2" target="_blank">https://github.com/infamous/infamous/blob/develop/src/core/ImperativeBase.ts#L2</a></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">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,</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">```js</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">class One {</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">  doOne() { /* ... */ }</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">}</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">class Two {</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">  doTwo() { /* ... */ }<br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">}</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">class Three {</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">  doThree() { /* ... */ }</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">}</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">```</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">a Proxy-based multiple inheritance system makes the composition super easy, clean, and simple. We can convert the previous example into:</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">```js</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)">import mix from './mix'</div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><br></div><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0)"><div class="gmail_default">class One {</div><div class="gmail_default">  doOne() { /* ... */ }</div><div class="gmail_default">}</div><div class="gmail_default"><br></div><div class="gmail_default">class Two {</div><div class="gmail_default">  doTwo() { /* ... */ }<br></div><div class="gmail_default">}</div><div class="gmail_default"><br></div><div class="gmail_default">class Three extends mix(One, Two) {</div><div class="gmail_default">  doThree() { /* ... */ }</div><div class="gmail_default">  doAll() {</div><div class="gmail_default">    this.doOne()</div><div class="gmail_default">    this.doTwo()<br></div><div class="gmail_default">    this.doThree()<br></div><div class="gmail_default">  }</div><div class="gmail_default">}</div><div class="gmail_default">```</div><div class="gmail_default"><br></div><div class="gmail_default">All without touching the original source of the `One` and `Two` classes. How convenient, and easier to read and look at!</div><div class="gmail_default"><br></div><div class="gmail_default">My particular implementation will allow to call individual constructors with specific args, unlike the class-factory mixins. For example,</div><div class="gmail_default"><br></div><div class="gmail_default"><div class="gmail_default">```js</div><div class="gmail_default">import mix from './mix'</div><div class="gmail_default"><br></div><div class="gmail_default"><div class="gmail_default">class One {</div><div class="gmail_default">  constructor(arg1, arg2) {/*...*/}</div><div class="gmail_default">  doOne() { /* ... */ }</div><div class="gmail_default">}</div><div class="gmail_default"><br></div><div class="gmail_default">class Two {</div><div class="gmail_default">  constructor(arg3) {/*...*/}<br></div><div class="gmail_default">  doTwo() { /* ... */ }<br></div><div class="gmail_default">}</div><div class="gmail_default"><br></div><div class="gmail_default">class Three extends mix(One, Two) {</div><div class="gmail_default">  constructor(arg1, arg2, arg3) {</div><div class="gmail_default">    this.callConstructor(One, arg1, arg2)</div><div class="gmail_default">    this.callConstructor(Two, arg3)<br></div><div class="gmail_default">  }</div><div class="gmail_default">  doThree() { /* ... */ }</div><div class="gmail_default">  doAll() {</div><div class="gmail_default">    this.doOne()</div><div class="gmail_default">    this.doTwo()<br></div><div class="gmail_default">    this.doThree()<br></div><div class="gmail_default">  }</div><div class="gmail_default">}</div><div class="gmail_default">```</div><div class="gmail_default"></div></div></div><div class="gmail_default"><br></div><div class="gmail_default">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).</div><div class="gmail_default"><br></div><div class="gmail_default">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.</div><div class="gmail_default"><br></div><div class="gmail_default">All the best,</div><div class="gmail_default">- Joe</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 22, 2019 at 3:55 AM Cyril Auburtin <<a href="mailto:cyril.auburtin@gmail.com" target="_blank">cyril.auburtin@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">It's not answering your issue with Proxy but more about multiple inheritance<div><div><br></div><div>It can be solved in a static way: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Mix-ins" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Mix-ins</a></div><div><br></div><div>Concrete example here: <a href="https://github.com/pepabo/gmopg/blob/master/src/gmopg.ts#L10" target="_blank">https://github.com/pepabo/gmopg/blob/master/src/gmopg.ts#L10</a></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 22, 2019 at 4:23 AM #!/JoePea <<a href="mailto:joe@trusktr.io" target="_blank">joe@trusktr.io</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">After messing with Proxy-on-prototypes for two days, I've just come to<br>
the conclusion that I probably need to have Proxies on this (the<br>
receiver) returned from constructors to achieve what I want. At least,<br>
it's much easier to code it that way. I think it'd be nice to have<br>
receiver on all inheritance-related traps. That might make some things<br>
easier.<br>
<br>
On Thu, Nov 21, 2019 at 2:55 PM #!/JoePea <<a href="mailto:joe@trusktr.io" target="_blank">joe@trusktr.io</a>> wrote:<br>
><br>
> I really thing that because `has` is about detecting inherited<br>
> properties, the `receiver` parameter should be included. For things<br>
> like `ownKeys`, which are not about inheritance, then yeah, let's not<br>
> add receiver there.<br>
><br>
> I'm trying to implement my own multiple inheritance, but now I<br>
> stumbled on how to make it send back true for inherited keys when I<br>
> need to fork the lookup based on instances that are `WeakMap`ed to the<br>
> `receiver`.<br>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>