-
-
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
[BUGFIX release] Simplify factory instantiation #19088
Conversation
Removes `_initFactory` as a method and instead sets the owner factory directly in an INIT_FACTORY_MAP. If the factory being initialized extends from CoreObject, it will pull the factory off immediately and use it. Simplifies passing the owner to CoreObject as well. The owner is now always passed as an injection, then plucked off and passed as the first argument to the constructor. It is not gotten through side-channeling the factory at all.
FrameworkClass limited the owner injection to just a few specific classes, but the brand check required to figure out what those classes were was costly. This removes it and updates to passing the owner to any object that extends from CoreObject.
Converts to native symbol in as many places as we can, and uses the benefits of native symbols non-enumerability in a few places, such as assigning properties OWNER to the instance of CoreObject/EmberObject. A few symbols still need to be enumerable, either because they are passed into mixins (which do not support non-enumerable symbols) or because we use enumerability in other ways. We should look into removing these in the future.
|
packages/@ember/-internals/runtime/tests/system/core_object_test.js
Outdated
Show resolved
Hide resolved
1ad23fe
to
60453d0
Compare
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.
Changes generally look good to me, only a few remaining concerns from my perspective:
- What enumerable properties remain on an object if it operates with the right protocol? Specifically, does
Object.keys(EmberObject.create())
return anything, is it platform dependent? I think we need to bring back tests for this, it has been important in the past. IMHO, if we end up increasing the number of own properties this probably can't land inrelease
(e.g. it would at least need to flow through the beta cycle). - Should we consider adding a version of
setOwner
that does not setLEGACY_OWNER
(either another export, or a third argument)? I'd much prefer to never exportOWNER
and force all users (internal and external) through the same protocol... - I haven't looked at what is up with the tests.
60453d0
to
29a6513
Compare
Added a test for this. No enumerable properties are added, on any platform, for
We also need to export the symbols for defining the getter/setter in IE11, which is how IE11 makes these properties non-enumerable on CoreObject. Definitely agree though, we should force everything through the protocol once we drop support for older platforms.
Fixed them! IE11 test was failing because we defined the non-enumerable getter/setter on EmberObject, not CoreObject, and we always set those properties on CoreObject now (so we don't have to do any checks to see if they're undefined). Moved the getter/setter to CoreObject instead, it makes sense to have them there. |
@@ -470,8 +468,12 @@ function buildInjections( | |||
typeInjections: Injection[], | |||
injections: Injection[] | |||
): BuildInjectionsResult { | |||
let injectionsHash = {}; | |||
|
|||
injectionsHash[OWNER as any] = container.owner!; |
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.
Don't we need both OWNER
and LEGACY_OWNER
? Specifically, if you were using a non-Ember.CoreObject
based class with a static create
...
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.
So, if we add LEGACY_OWNER here, it will result in an enumerable LEGACY_OWNER property on Ember.CoreObject unless we delete it or purposefully ignore it, which seems bad.
Given that Symbol works with Object.assign
, I think it should be fine in most real use cases to just do this. The only one we've seen that relied on enumerability used setOwner
, not the container API.
If we do think we need it though, I think we have to accept that CoreObject will need to do a bit more work to ignore it.
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.
Sadly, I do think we should do this. An idea that @pzuraq came up with in chat was to make this use setOwner
(and therefore set LEGACY_OWNER
) but also add a set [LEGACY_OWNER]() {}
on CoreObject
to "black hole" the property (and avoid enumerability).
|
||
let type = typeof method; | ||
if (type === 'string' || type === 'symbol') { | ||
method = target[method as string] as Function; | ||
} | ||
|
||
method.apply(target, params); | ||
(method as Function).apply(target, params); |
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.
Did we resolve the perf concern here? Should we do this (which is what I think I had suggested/mentioned), or go back to:
if (typeof method === 'string' || typeof method === 'symbol') {
method = target[method] as Function;
}
packages/@ember/-internals/runtime/tests/system/object/create_test.js
Outdated
Show resolved
Hide resolved
29a6513
to
035f61b
Compare
035f61b
to
56495f7
Compare
Simplifies factory instantiation and object creation in a number of ways:
create
.See the individual commits for more detailed explanations of the changes.
Benchmark results:
artifact-64.pdf