-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Array index assignment does not work in Safari #364
Comments
Do you get an exception or something like that? (sorry, no IOS device at hand) |
I tested on Safari 8.0.8 and got: [Log] Remaining: Make coffee It looks like being a jsfiddle safari problem. It's correct on firefox. |
I originally found the bug in our code, which means its not specifically related to JSFiddle. You get no errors at all. When you assign an object like, the keys in that object are not observed so that if you change one later it never recognises the change.
|
@elliotchance sorry for the late response! I'm back in town and just tried in on iOS9 device, indeed it doesn't run as expected. For others, to verify, just use this fiddle: https://jsfiddle.net/yfkkk42r/5/. If you don't see "iOS9 bug not present", the bug is present. Thanks for reporting, this is an important issue! |
@mweststrate, the bug is also present on Desktop Safari 9.1.1 Seems, like Safari doesn't respect setting numbered setters on array-like constructor's prototype: Object.defineProperty(ObservableArray.prototype, '9999', {
enumerable: false,
configurable: false,
set: function() { alert('hello'); },
get: function() { return 0; }
});
Object.defineProperty(ObservableArray.prototype, 'zzzz', {
enumerable: false,
configurable: false,
set: function() { alert('hello'); },
get: function() { return 0; }
});
var x = new ObservableArray(1);
x['zzzz']; // ok, returns 0
x['zzzz'] = 5; // ok, alerts 'hello'
x['9999']; // ok, returns 0
x['9999'] = 5; // fail, does nothing
x['9999']; // fail, returns 5, property redefined |
I'll do additional envestigations tomorrow |
@andykog awesome! Thanks in advance |
I have more precise example, that represents the problem: function O() {}
var val;
Object.defineProperty(O.prototype, '1', {
set: function() { val = '~~~ok~~~'; },
});
var x = new O();
x['1'] = 'something';
console.log(val); // undefined I don't think there is a way to fix this behaviour. Safari won't use prototype's setter for number. It is fixed in Safari 9.1.2 Technology Preview. @mweststrate, I think, the only way to fix this issue is to detect if the bug is present in browser, and, if yes, to define getters/setters on instance, loosing performance. Is it ok? |
@andykog did you try to use numbers as property keys? I think for MobX it actually doesn't matter much, not sure about that anymore whether the stringification was to satisfy the compiler or to fix something real. Otherwise falling back to non prototype properties if they don't work sounds like a very nice solution! |
@mweststrate, it doesn't matter, using numbers ( |
@andykog If you need any help btw, or don't have the time for it, just let me know! |
|
I believe, I'll have time to dive in this tommorow. By the way, did you ever tried to run tests in a real browser? I'm getting very strange results:
Firefox:
Safari:
Pushed e8a461c so you can try |
Note: caching the property descriptors per index makes sure that at least the memory consumption doesn't increase significantly when defining them on the instance: 3635fa2 |
@mweststrate, are you going to merge 3635fa2 into master? Actually, this fixes Safari bug… |
definitely! I'll try to publish it in a few hours Op do 7 jul. 2016 19:07 schreef Andy Kogut notifications@github.com:
|
You've accidentally found a good workaround! If you define at least 1 property that looks like number on instance, the bug disappears. This doesnt work in safari: const xPrototype = {};
Object.defineProperty(xPrototype, "1", {
set: () => { alert("Got new value!") }
});
const x = Object.create(xPrototype);
x[1] = 1; But this, actually does: const xPrototype = {};
Object.defineProperty(xPrototype, "1", {
set: () => { alert("Got new value!") }
});
const x = Object.create(xPrototype);
x[999999] = 5; // <- the fix
x[1] = 1; |
Wow, that is really weird! Man, how did you even find that?! So your proposal is to simply fix this by assigning some value to |
I just tested your branch 'enumerable-arrays' in safari, saw that it passes tests so I just found out why.
|
Would you mind submitting a PR? I don't have a Mac so testing a patch would require me to distract my wife and then sneak away with her IPad 🎃 |
Of course!
|
@mweststrate, there you go: #396 |
Released as |
In Safari 9.1 assigning an object to an array by index breaks anything after that:
https://jsfiddle.net/yfkkk42r/2/
Open the same URL in Chrome and it will work correctly.
The text was updated successfully, but these errors were encountered: