Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Attempted to assign to readonly property. in Angularjs application on iOS8 Safari

Our Mobile App is getting "TypeError: Attempted to assign to readonly property." only on IOS 8 and the stack traces are not helpful and seem to be in Angular code.

This might be happening because of the "use strict" on top level of Angularjs code. My questions are (1) why did it start happening only on IOS8? is this an IOS8 bug? (2) or is this an angular bug surfaced on IOS8? (3) Or maybe we are violating strict mode rules but only IOS8 started to catch them! I am skeptical about the third option because strict mode is supported by other major browsers.

I have found one similar reported issue here.

like image 628
Sara Navidpour Avatar asked Sep 25 '14 16:09

Sara Navidpour


2 Answers

Looks like this is an IOS8 bug

At least the guys at ember.js will temporarily strip the 'use strict' from their code until it's fixed. Ember.js issue

like image 108
Daniel Riquelme Avatar answered Sep 22 '22 16:09

Daniel Riquelme


SOLUTION - Note:

  1. angular.copy didn't work for me
  2. lodash cloneDeep didn't work either.
  3. removing "use strict"; didn't help - It just removed the error being logged in a try/catch arround the "erroneous" assignment to a readonly value

For us, the value that was being passed back from the SQL promise value was an array of objects.

The values that we were getting "read only" error on were strings, bools, and numbers.

console.log('this will log');
sqlReturnArray[0].name = "Bob"; // read only error here
console.log('wouldnt get to here to log');

I figured, well, if I can't assign values to properties on THOSE objects within the array, why can't I just copy over all the objects' values? Assignment of objects is by reference so just doing a loop over the array won't help. You need to loop over the keys and values.

This solved our problem

// where sqlReturnArray is the object given from the SQL promise
var newArrayOfObjects = [];
angular.forEach(sqlReturnArray, function (obj) {
  var newObj = {};
  angular.forEach(obj, function (val, key) {
    newObj[key] = val;
  });
  newArrayOfObjects.push(newObj);
});
like image 29
Brian Schermerhorn Avatar answered Sep 20 '22 16:09

Brian Schermerhorn