From d2aa1271805f02c2afde86bb1944d7bd4395dfaa Mon Sep 17 00:00:00 2001 From: Daniel C Date: Tue, 27 Jun 2017 23:26:53 +0300 Subject: [PATCH] localStorage: bring back proxy methods to to window.localStorage. (Fix IE11 issue) IE11 doesn't handle properly attempts to change methods of the window.localStorage, attempts to do so will result in the complete break of the localStorage system for the domain in which it is done - until the user clean the browser/domain cache. Therefore, in the web, we don't set Meteor._localStorage to be a reference to window.localStorage . Instead, we set proxy methods. This will allow package developers that will find a need to change the behavior of Meteor._localStorage methods to do so without breaking the localStorage system on IE11. (e.g. meteorhacks:fast-render) IE11 (earlier IE versions weren't checked) doesn't handle attempts to replace methods of window.localStorage with different functions properly. Such attempt will result in the String of the function we try to set saved as the function, destroying the ability to use this function. I couldn't find a way to tell in advance whether an attempt to set window.localStorage will result in correct function write or not (I intentionally avoid browser version detection, which is considered a bad practice). If such attempt will fail we won't have a way to restore the original function. The situation is even worse than that. If for exapmle we'll try to set window.localStorage.setItem = function () {} the String value 'function () {}' will be saved instead of the function - not only for the current session, but as part of the localStorage (!) meaning that we'll have to ask users affected by this bug to clear the cache to fix the situation. The following won't work: ```javascript Meteor._localStorage = window.localStorage // Just to make example clear. originalSetItem = Meteor._localStorage.setItem Meteor._localStorage.setItem = function () {} Meteor._localStorage.setItem = originalSetItem typeof Meteor._localStorage.setItem -> string ``` --- packages/localstorage/localstorage.js | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/localstorage/localstorage.js b/packages/localstorage/localstorage.js index c943385137..70907463d7 100644 --- a/packages/localstorage/localstorage.js +++ b/packages/localstorage/localstorage.js @@ -21,7 +21,33 @@ try { } catch (ignored) {} if (key === retrieved) { - Meteor._localStorage = storage; + if (Meteor.isServer) { + Meteor._localStorage = storage; + } else { + // IE11 doesn't handle properly attempts to change methods of the + // window.localStorage, attempts to do so will result in the complete + // break of the localStorage system for the domain in which it is + // done - until the user clean the browser/domain cache. + // + // Therefore, in the web, we don't set Meteor._localStorage to be a + // reference to window.localStorage . Instead, we set proxy methods. + // + // This will allow package developers that will find a need to change + // the behavior of Meteor._localStorage methods to do so without breaking + // the localStorage system on IE11. (e.g. meteorhacks:fast-render) + + Meteor._localStorage = { + getItem: function (key) { + return window.localStorage.getItem(key); + }, + setItem: function (key, value) { + window.localStorage.setItem(key, value); + }, + removeItem: function (key) { + window.localStorage.removeItem(key); + } + }; + } } if (! Meteor._localStorage) {