-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP es-classes] Fix extending from ES Classes #16184
Conversation
let initProperties, initFactory; | ||
|
||
class Class { | ||
constructor() { | ||
let self = this; | ||
|
||
if (!wasApplied) { | ||
Class.proto(); // prepare prototype... | ||
if (!meta(this).parent.wasApplied) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit of a hack, I found that in some cases (particularly ObjectProxy
) the following would be true:
let m1 = meta(this);
this.constructor.proto();
let m2 = meta(this);
m1 !== m2
For some reason, proto
can confuse meta this way (something to do with the way WeakMap
links between objects and values?). On the otherside, if we were to do:
meta(Object.getPrototypeFor(this)).wasApplied
The meta for a native class does not have proto
set (it was created outside of extend
, no chance to add it) so the check in the getter/setter for wasApplied
fails.
I think ideally we only load meta once, and just use the parent
value.
I believe that this is indeed going down the right path... |
@pzuraq - Mind rebasing on top of the "single constructor arg" work? |
8b91e86
to
5fac5bb
Compare
Rebased! I should have some time later on this week to work on this so let me if there are any specific changes I should make. I want to try to get rid of the |
5b1a7fd
to
b89d223
Compare
Alright, this is ready for review! Turned out the Here are the perf benchmarks, taken just before I added some tests (will redo them with the current git hash shortly). I ran 100 samples, and unfortunately it does look like this is a minor regression: |
@pzuraq that isn't a significant result, it has too high of a chance of incorrectly rejecting the null hypothesis. |
Alright, so should I rerun with more samples? Or is this good enough to merge? Currently on vacation but I’ll get it rebased as soon as I get back! |
b89d223
to
40c2eb2
Compare
FYI - I just rebased it (@krisselden and I are poking at this stuff, so figured I'd rebase while I was in there...) |
👍 I can look into the test failures as soon as I’m back next week |
This has been superceded by a better strategy implemented in #16436 |
This PR seeks to fix the behavior of ES classes, specifically when calling
.extend()
on a native class. Currently, a new base class constructor (makeCtor
) is made each time we call.extend()
. With ES classes, this no longer works as expected because the base class does not ever call it's super constructor, breaking both the constructor of the native class and (in the future) class fields, which are assigned in the constructor.The changes here detect if the class being extended from is actually a
makeCtor
, and if not provide a simple anonymous class that extends from the superclass instead. This allows the constructor to follow the prototype chain upward instead to whatever the last realmakeCtor
was, which then does all of the work of assigning properties, runningproto
, etc. In order to do this, metadata such aswasApplied
had to be moved to the meta object for the object (see #15580) and static methods such asproto
had to remove direct references to the class inmakeCtor
itself so they could be reused for upstream classes.TODO:
reopen
andreopenClass
, particularly when they retrigger aproto
reopen
andreopenClass
fail on native classes