Closed HAKASHUN closed 8 years ago
Which version of angular did you test? Does it appear simply by including angular or under specific circumstances (your app code)?
I tested AngularJS v1.2.25.
My app code is below.
...
<card-item-list ng-repeat="card in cards track by $index" data-card="card"></card-item-list>
...
var cardItemList = function() {
var link = function(scope) {};
return {
restrict: 'E',
replace: true,
templateUrl: 'templates/card/directives/list-item.html',
scope: {
card: '=',
},
link: link
};
};
cardItemList.$inject = [];
...
<div class="card--list__item">
<div ng-class="{'card--list__item_state_check': card.isSelect}">
<card-thumb data-card="card"></card-thumb>
</div>
<p class="card--list__item__detail fs_xxs">
<span ng-if="card.parameter.attack > 0">{{card.parameter.attack}}<br> </span>
<span ng-if="card.parameter.defense > 0">{{card.parameter.defense}}<br>{{card.parameter.speed}}</span>
</p>
</div>
...
var cardThumb = function() {
return {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: ''templates/card/directives/card-thumb.html',
scope: {
card: '=',
opts: '=?'
},
link: function(scope, element){
}
};
};
cardThumb.$inject = [];
...
<figure class="thumb thumb_type_1">
<img class="thumb__img" ng-src="{{card.image_path}}" ng-if="card.master_id">
<figcaption class="thumb__caption" ng-transclude></figcaption>
</figure>
@christianv could you please put together a http://plnkr.co/ or http://jsbin.com/ to reproduce this?
I'll see if I can repro this on my ipad or iphone 6 (but, from what you said, it sounds like I might not be able to :()
@caitp I think you meant to notify someone else.
yeah I meant @HAKASHUN, sorry
remove 'use strict' and try
we get the same issue, and @HAKASHUN's code fixed the issue for us
We get the same issue.
I applied @HAKASHUN's code to v1.2.26
https://github.com/shunjikonishi/angular.js/commit/b91f34103974047708145e971506f354f804c17c
When I include angular.js, it works fine. But with angular.min.js, it doesn't work.
I hope to fix this problem with both of normal and minified version.
We have also experienced this error with several different iPads, all running iOS 8. I can get exact model numbers if anybody is interested. We have tried builds with Angular versions: 1.2.24, 1.3.0, and 1.3.1
@HAKASHUN's fix has worked at least in debug (non-minified) builds.
@shunjikonishi this is just a guess (I'm dealing with the same issue) but does your minifier perhaps do something like forcing dot notation? That would effectively undo this fix. I've tried one minification with uglify (2.4) and it broke the fix, and now I'm looking into my guess. Perhaps I can ask uglify to respect dot notation, or maybe I'm way off.
update
Is anyone else using $route?
Also @shunjikonishi in my case, uglifyjs was forcing dot notation, effectively undoing the fix. If you're using grunt/uglify it's something like: uglify: { options: { properties: false }}
could you make a quick reproduction of this? I'd like to see it with my phone
@caitp I will see what I can do. I've got some unexpected work to take care of, but this is important, so hopefully I will have a plunker by the afternoon.
update
@caitp I made a plunker to attempt to reproduce this issue, and failed.
If anyone is interested in looking at my plunker attempt at reproducing, it's here: http://plnkr.co/edit/EPsxhO1OsD5MmnUyl50t?p=preview I started with a simple click updating a $scope, then tried $route changes (which is where I can consistently reproduce in my app), and then tried repeats, and a repeat in an ng-if.
I will put more time into this later.
@bennett000 Thank you for advise.
I just used output of grunt package command.
Now, I include uglify angular task in my project. It works fine.
There is one correction. With grunt-contrib-uglify, its option format is like this.
uglify: {
options: {
compress: {
properties: false
}
}
}
This also appears to affect Angular v1.3.0; we've seen it on an iOS8 device in our office, but the page it's on hits the error inconsistently (something we're researching).
Applying @shunjikonishi 's patch causes the page not to break under those conditions, but also causes "undefined" to appear on the page in places it shouldn't, and not to be removed.
Perhaps not the most useful set of details, but this is the result of an initial investigation. We can dig deeper; just wanted to note that v1.3.0 is also affected.
hey guys, we're still waiting for a reproduction =)
(so please provide one)
@caitp absolutely, reproducing the error consistently is essential.
What's odd is that I can reproduce this consistently in my application, as can others; yet I failed to reproduce in a plunker. I'm happy to keep working on reproducing this in an example, but I'd really like to get more details from other people who have this issue.
In our case:
iDevice model numbers known to be affected:
I'm wondering if there is a difference if the application is run from the iOS home screen, as opposed to being run in iOS Safari, or in a WebView, or WKView; this has been the case in older iOS versions.
I will work more on a plunker, and I will also take the plunker code, and spin it into a self contained application so I can see if I can reproduce it when "saved" to the iOS home screen.
Again, any extra information anyone else has about their issues would be helpful.
update
Dropping the existing plunkr stuff I had done into a full blown iOS homescreen web app does not seem to have had any additional effect.
Is anyone else using any custom gestures, or doing anything special to avoid things like iOS's bounce scrolling?
Removing the 'use strict';
solve the issue for me (iPhone 5C iOS 8.1).
Over the last few weeks I continued to fail to reproduce this problem in a controlled environment, like a plunkr. On top of that, other workarounds, including removing 'use strict' do not help me. Obviously without a controlled reproduction of this issue there's nowhere to begin solving this problem. However it occurred to me that Angular ships with its own unit test suite; how do those tests perform on my devices?
Mobile Safari 8.0.0 (iOS 8.1.1) private mocks createMockStyleSheet should allow custom styles to be created and removed when the stylesheet is destroyed FAILED Expected '0px' to be '2px'. ~/Workspaces/angular.js/test/helpers/privateMocksSpec.js:23:47
My guess is that this failed test is unrelated.
Again, anyone with any suggestions on how to reproduce the iOS 8 readonly error would be helpful. I do know other frameworks have had similar issues with readonly property assignments in iOS8.x but they have not helped me reproduce. Here are the links that reference the similar issues some others have encountered
Other steps I've taken to mitigate this problem have been to comb over our entire source, and the source of every library we use to find anything that might set a property read only. This includes grepping for:
Is there anything else that might make JavaScript throw a type error read only? Not being able to reproduce this is not helping my sanity.
We are also running into this. We were able to reproduce the problem only on the actual device (in our case IPhone 5C) with an IOS version prior to 8.1 (we're testing on 8.0.2 and the problem recurs continuously).
This is quite a serious issue, is there any known workaround?
(We're on Angular 1.3.6, updated today, problem still persists)
@m3kka did you manage to isolate the problem? It will be very hard to move on this one without narrowing it down first.
Spent the afternoon looking for a way to reproduce the error in a controlled environment but still no solutions sadly.
I've expanded a bit the workaround of @HAKASHUN so if anyone needs a fast - notSoGood - fix this is what I did.
AngularJS ver. 1.3.6:
RootScope https://github.com/angular/angular.js/blob/master/src/ng/rootScope.js#L208 From:
if (!this.$$ChildScope) {
this.$$ChildScope = function ChildScope() {
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
this.$$listeners = {};
this.$$listenerCount = {};
this.$id = nextUid();
this.$$ChildScope = null;
};
To:
if (!this['$$ChildScope']) {
this['$$ChildScope'] = function ChildScope() {
this['$$watchers'] = this['$$nextSibling'] =
this['$$childHead'] = this['$$childTail'] = null;
this['$$listeners'] = {};
this['$$listenerCount'] = {};
this['$id'] = nextUid();
this['$$ChildScope'] = null;
};
https://github.com/angular/angular.js/blob/master/src/ng/rootScope.js#L221 From:
child.$parent = parent;
child.$$prevSibling = parent.$$childTail;
To:
child['$parent'] = parent;
child['$$prevSibling'] = parent.$$childTail;
Compile https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L1375 From:
transcludedScope.$$transcluded = true;
To
transcludedScope['$$transcluded'] = true;
Until now I am not able to help you with more informations, will keep looking into the issue.
I figured this one out. iOS dies on this line:
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
When I broke this out into separate statements, I found the error was caused when this.$$watchers
was assigned first. The following worked correctly:
this.$$childTail = null;
this.$$childHead = null;
this.$$nextSibling = null;
this.$$watchers = null;
I suspect iOS executes the order of the assignment incorrectly, causing the error. I don't know where else this syntax difference would cause errors, but I suspect it has far reaching implications.
@Wasmoo wow, this sounds strange. Are you able to isolate this thing in a minimal example, ideally in plunker? If so this would be definitively an issue on the browser side.
@pkozlowski-opensource Unfortunately no. I just ran into the error on the project I'm working on and I have no idea of its source (jQuery throws something at Angular). As it is in my project, you have to click on just the right things in just the right order to get the error to occur, but this and only this change fixes my problem.
Hopefully someone else who is getting the error can confirm the fix.
We are experiencing this problem in 'heavy' page filled with several scopes and template, simplifying this out in a plunker seems really difficoult :/
I'll try @Wasmoo's fix out, will post back the result on our codebase in a couple minutes.
Nope @Wasmoo's is not solving the issue in our codebase.
:-( Sadness! I also confirmed that iOS does assignment in this syntax in the correct order:
j.a = j.b = j.c = 0;
is equivalent to
j.c = 0;
j.b = 0;
j.a = 0;
So that throws that theory out, though I can't explain why my fix works for me.
For what it's worth, my project is still broken - my fix only moved the bug so it fails in the same way at some other point.
@Wasmoo by applying my workaround you should be able to remove the problem (still you're gonna have to maintain for the next angular versions)
@m3kka Works like magic!
@m3kka would it mean that Safari on iOS doesn't like dotted access to properties staring with $
? Hmm, there must be something additional going on...
Here's a monkey patch I created to not have to modify the angular.js source code directly. I've been using it for the past few weeks with no more issues. It was based on angular 1.3.3.
https://gist.github.com/jhunken/767cdf62ecc9f31c56da
I also haven't been able to reproduce this issue with a minimal example unfortunately.
If someone is looking for a solution without having to use a patched version of Angular, you could try the following.
I had a couple nested state controllers for ui-router and noticed the error was being triggered by a couple lines that were accessing variables on a parent scope. In an attempt to gain access to these variables without going through the scope I set up my controller using the Controller as
syntax. This made it so I could access the variables directly without having to traverse up the scopes.
Not sure if this will work for everyone but my application no longer throws the error.
@pkozlowski-opensource I think that IOS is somehow messing up with the readonly property on js objects. Apparently accessing the elements with the 'key notation' (can't remember the actual name) ignores this mess up.
Also apparently Angular is not the only one affected by this issue -http://craigsworks.com/projects/forums/showthread.php?tid=3649
@jhunken You made me bash my head. Should have used decorators from the beginning. Thank you :)
I have the same problem. Suggested workaround seems to solved it. I use @jhunken's decorator.
Noob question: what does this issue being in purgatory milestone mean? It doesn't sound good.
I still have yet to reproduce this, and I have wasted a lot of time trying. I am however happy to say that @jhunken 's monkey patch seems to have solved my problems for now. I look forward to figuring out why this works since I squandered so much time stepping through this process over/over without getting any results.
Adding some details that probably are not useful on their own, but... On iOS 8.1.2 iPad 2 and mini I have seen the "TypeError: Attempted to assign to readonly property". It's a large app, so hard to get into plunkr.
We had the issue appearing consistently using Angular 1.3.7 (we had removed 'use strict' from the min file for v1.3 to fix this same problem, but didn't remove it after the upgrade). Last time the error was popping up in a different place in the app and was less consistent. This time we had repro steps to do it on demand. Removing 'use strict' from angular.min.js fixed the issue. The final step before the error involved changing the route (we use the standard router: ngRoute). In our case this resulted in a data grid with no data and the messages weren't translated (using the translate directive from pascalprecht.translate). Switching the route again using the same dropdown or refreshing would get the page working again.
I do believe this is a mobile safari bug because we do not see it in any other browser.
This seems to be an iOS 8 bug - http://stackoverflow.com/a/27401601
On bugsnag error logs for my application I also see that only on Mobile safari with iOS 8.0 and 8.1
Below is a stack trace for angular 1.2.28. The same issue is there also for 1.2.24.
TypeError Attempted to assign to readonly property.
angular.js:12188:37 $$childScopeClass
angular.js:12198:8 prototype
angular.js:6161:29
angular.js:6773:35 controllersBoundTransclude
angular.js:21409:16 link
angular.js:6752:19 nodeLinkFn
angular.js:6146:23 compositeLinkFn
angular.js:6746:35 nodeLinkFn
angular.js:6954:36
angular.js:8171:13
angular.js:11682:81 wrappedCallback
angular.js:11768:34
angular.js:12811:28 prototype
angular.js:12623:36 prototype
angular.js:12915:12 prototype
angular.js:19264:29
angular.js:2853:14
angular.js:325:22 forEach
angular.js:2852:12 eventHandler
Is there any other fix for this besides removing 'use strict'? I would like to CDN angular and this would disable it...
edit: using gist works. sorry about that
Monkey patching worked for me too, Obviously not a good solution, and this is a bug that is breaking angular out in production. Looks like ios8 webkit really dislikes assignment of .$$variables
For some info, I had to patch compile.js as my directives compile phase was being borked.
transcludedScope['$$transcluded'] = true;
Making some changes from dot notation to brackets notation by monkey patching like @jhunken did worked for me too. Very strange problem.
Still no word about an official solution?
Removing use strict did it for me. Still waiting on the official solution though.
@rjbernaldo To clarify, are you removing 'use strict' from angular.js, your own source files, or both?
@hamstu I removed it from angular.js only.
Removing 'use strict';
fixed the issue on my end as well. I'm fairly convinced Apple is trying to kill off web-apps with breakage like this. =]
Removing 'use strict';
did stop the crashes but seems to have caused another problem: now my app seems to hang instead of crashing, and the tab in Safari becomes totally unresponsive. This even happens in the iOS simulator, and the simulator process starts using 200% CPU on my mac.
Has this happened to anyone else?
could you post a stack trace of the crash, along with versions of al the libraries you're using? that would be helpfulp.
oh hang on, I see what it is... wow I don't think that's the right behaviour in JSC, but just to check...
I haven't been able to reproduce this on my iphone, ipad, or any of the ios simulators I've tried. It looks to me like the issue is the prototype
property being incorrectly defined as non-writable in JSC, which would be a bug (and, would explain why it's no longer reproducible if they've fixed it). If that's not the bug being hit, then please supply a reproduction for us.
I am using on iOS 8 GM(iPhone5C). With this device, I am getting this error in this line(https://github.com/angular/angular.js/blob/master/src/ng/rootScope.js#L216) But on iOS 8 GM(iPhone5S) and iOS 7.x (iPhone5C, iPhone5S), this error does not occur.
To resolve this error, I rewrote the code as follows:
The situation has improved, but I do not understand the reason...