-
-
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
[3.16] Bug with set
and array
#18739
Comments
The issue is that the mandatory setter code is not distinguishing between FWIW, you probably shouldn't be using Also, you can implement a custom "array" by implementing the following methods/properties on any class:
It should work in general in the system if it has all of those, and doesn't need to extend from Edit: Also notify the |
Ah, interesting. So when you remove the item from the array, it also splices out its property descriptor, which is why there's a mismatch with mandatory getters/setters here. I don't think mandatory setters really make sense in this case. Will add a PR to remove. |
@pzuraq - thanks for the detailed explanations as always!
As for the internal array representation - I'm not sure why that would be more performant... what I have exactly is as follows: const properties: ThisType<ISmartMutableArrayProxy<T>> = {
objectAt(index: number): T | undefined {
...
},
unknownProperty(key: string | number): T | undefined {
...
},
firstObject: computed('0', {
get(this: ISmartMutableArrayProxy<T>): T {
...
},
set(this: ISmartMutableArrayProxy<T>, _, value: any): T {
...
},
}),
lastObject: computed('length', {
get(this: ISmartMutableArrayProxy<T>): T {
...
},
set(this: ISmartMutableArrayProxy<T>, _, value): T {
...
},
}),
setUnknownProperty(key: string | number, value: any): T {
...
},
replace(index: number, amount: number, objects = []): ISmartMutableArrayProxy<T> {
...
},
includes(object: any, startAt?: number): boolean {
...
},
// TODO: remove `insertAt`, `removeAt`, `pushObject` and `unshiftObject` when https://github.com/emberjs/ember.js/issues/17282 is fixed
insertAt(idx: number, object: any): ISmartMutableArrayProxy<T> {
...
},
removeAt(start: any, len = 1) {
...
},
removeObject(object: any): ISmartMutableArrayProxy<T> {
...
},
pushObject(obj: any): any {
...
},
unshiftObject(obj: any): any {
...
},
};
const result: ISmartMutableArrayProxy<T> = Mixin
// @ts-ignore
.create(MutableArray, Observable, properties)
// @ts-ignore - without is private API
.without(['length'])
.apply(array); As you can see, I'm just implementing a couple of methods in my own way and reusing most of the functionality in the Mixins. The implementations are kind of straight-forward so the performance shouldn't be (much) worse than a normal array, I guess? Not sure what you meant by the last comment - is that a bug after all? Is your PR going to fix it or just remove some unused code? Any ideas how to workaround the problem after all? |
@boris-petrov - Just to confirm, are you saying that this is a regression in 3.16? If yes, what was the last version that worked properly? |
Just thinking about this some more, and I had a couple more questions:
|
@rwjblue - I don't think this is a regression in 3.16 (although I'm not sure because I just found that bug). About your other points:
const result: ISmartMutableArrayProxy<T> = Mixin
.create(MutableArray, Observable, properties)
.without(['length'])
.apply(array); That is, I mixin
As for whether that PR will fix my problem... no idea. If it fixes the example in my first post, probably it will fix my use case too. I'll wait for a new release and try it out and I'll let you know. :) |
The following code:
Prints two times
2
. The same is true when usingEmber.set
instead of theset
method on the array.The funny thing is that removing either the
removeAt
line or theaddObserver
line fixes the problem.Any ideas for a workaround would be welcome as this is a problem for us.
P.S. Calling
x.replace(0, 1, [3]);
instead ofx.set(0, 3);
seems to work fine. However, this doesn't work in my case because I have a custom implementation of EmberArray and I've overwrittenreplace
to behave differently (that's why I'm callingEmber.set
internally and noticed that bug). How can I call the "original"replace
? I triedthis._super
and a few other things as well but to no avail.The text was updated successfully, but these errors were encountered: