Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Infinite digest on location change on iOS 9 w/ UIWebView (not in Safari/ WKWebView) #12241

Closed
ttopalov opened this issue Jun 30, 2015 · 154 comments
Closed

Comments

@ttopalov
Copy link

The following simple HTML demonstrates the issue:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular-route.js"></script>
        <script>
            angular.module('fail', ['ngRoute'])
            .config(function($routeProvider) {
                $routeProvider
                .when('/a', {
                    template: '<a ng-href="#/b">a</a>'
                })
                .when('/b', {
                    template: '<a ng-href="#/a">b</a>'
                })
                .otherwise({
                    redirectTo: '/a'
                });
            });
        </script>
    </head>
    <body ng-app="fail">
        <div ng-view></div>
    </body>
</html>

This runs as expected on most devices, but it throws an infinite digest exception on iOS 9.
I'm able to reproduce on both iPad Air 2 and iPad 4th generation with iOS 9 beta 2.
I realize it's probably an issue in iOS, but it might still be worth investigating.

@cxm01
Copy link

cxm01 commented Jul 1, 2015

I met similar issue, which happened on ios 9, but run ok on other devices.

@cxm01
Copy link

cxm01 commented Jul 2, 2015

I reproduced this issue with the same code provided by santaslow on 1.4.1 / ios 9:

<!DOCTYPE html>
<html>
<head>
    <script src="../static/js/angular/angular.1.4.1.js"></script>
    <script src="../static/js/angular-route/angular-route.1.4.1.js"></script>
    <script>
        angular.module('fail', ['ngRoute'])
                .config(function ($routeProvider) {
                    $routeProvider
                            .when('/a', {
                                template: '<a ng-href="#/b">a</a>'
                            })
                            .when('/b', {
                                template: '<a ng-href="#/a">b</a>'
                            })
                            .otherwise({
                                redirectTo: '/a'
                            });
                }).factory('$exceptionHandler', ['$log', function($log) {
                    return function(exception, cause) {
                        var message = 'angularjs exception: '+exception.message+': caused by "' + cause+ '\njs stack:\n'+exception.stack;
                        $log.error(message);
                    };
                }]);
    </script>
</head>
<body ng-app="fail">
<div ng-view></div>
</body>
</html>

The code above run normally on desktop browser, android and ios 8 webview, but on ios 9 it will throw exception when I click the link:

2015-07-02 11:00:09 ... angularjs exception: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.4.1/$rootScope/infdig?p0=10&p1=%5B%5D: caused by "undefined
js stack:
file:///.../static/js/angular/angular.js:68:32
$digest@file:///.../static/js/angular/angular.js:15705:35
$apply@file:///.../static/js/angular/angular.js:15935:31
file:///.../static/js/angular/angular.js:12070:30
eventHandler@file:///.../static/js/angular/angular.js:3264:25

@ttopalov
Copy link
Author

ttopalov commented Jul 9, 2015

I can no longer reproduce in iOS 9 Beta 3.

@ttopalov ttopalov closed this as completed Jul 9, 2015
@aexei
Copy link

aexei commented Jul 11, 2015

I receive the same error with ios9 public beta (13A4293g)

@cxm01
Copy link

cxm01 commented Jul 13, 2015

I verified the code above on ios 9 beta 3 (13A4293g), no exception anymore. But the app with using ng-view still throw infdig exceptions on ios 9 beta 3.

@arkomr
Copy link

arkomr commented Jul 13, 2015

I receive the same error with ios9 public beta (13A4293g)

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.13/$rootScope/infdig?p0=10&p1=%5B%5D
file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:8762:32
$digest@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:22980:35
$apply@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:23205:31
file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:54879:24
eventHandler@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:11713:25
dispatchEvent@[native code]
triggerMouseEvent@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:2863:20
tapClick@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:2852:20
tapTouchEnd@file:///Users/mac5/Library/Developer/CoreSimulator/Devices/749DE7E3-D93F-47F9-A1FC-E3D54A1CCEEE/data/Containers/Bundle/Application/9B5EE368-F2A0-4C99-807B-EA17B2479E58/BAShops.app/www/lib/ionic/js/ionic.bundle.js:2975:13

@epaga
Copy link

epaga commented Jul 15, 2015

We are also receiving this error on public Beta 3 of iOS 9 with our own Angular application. It does not occur in iOS 8.

@cxm01
Copy link

cxm01 commented Jul 15, 2015

As a workaround, I wrote a simple directive to replace ng-view and angular-route.js. The solution worked well in our own application, all infdig exceptions disappeared on ios 9 beta/beta 3. Below is the simplified code, which is just for our own application, general use cases are not considered. I DO NOT recommend other people to use this:

(function (window) {
    'use strict';

    var myApp = angular.module("myApp");
    var $route = {};

    // replace $routeProvider.when with the function below:
    window.routeWhen = function(path, route) {
        $route[path] = route;
    };

    myApp.directive("myView", ['$compile', '$controller', '$http', '$rootScope', function ($compile, $controller, $http, $rootScope) {

        return {
            priority: -400,
            link: function (scope, element) {
                var parentScope = scope;
                scope = null;

                window.updateView = function (path) {
                    location.hash = '#'+url;
                    if (scope) scope.$destroy();
                    scope = parentScope.$new();

                    var route = $route[path];

                    var linkView = function(html) {
                        element.html(html);
                        var link = $compile(element.contents());
                        var controller = $controller(route.controller, {$scope: scope});
                        element.data('$ngControllerController', controller);
                        element.children().data('$ngControllerController', controller);
                        link(scope);
                        scope.$emit('$viewContentLoaded');
                        if (!$rootScope.$$phase && !scope.$$phase) scope.$apply();
                    };
                    if (route.templateCache) linkView(route.templateCache)
                    else if (route.template) {
                        route.templateCache = document.getElementById(route.template).innerHTML;
                        linkView(route.templateCache)
                    }
                    else $http.get(route.templateUrl;).success(function(html) {
                        route.templateCache = html;
                        linkView(html);
                    });
                };
                //updateView(initialPath);
                // call updateView(path) to set location at other places of the app
            }
        };
    }]);

})(window)

@raftheunis87
Copy link

Just installed iOS 9 Beta 4 and still have the same issue. Anyone else?

@craig-at-rsg
Copy link

I saw it in iOS 9 Beta 3 and I'm still seeing it in iOS 9 Beta 4.

@aexei
Copy link

aexei commented Jul 22, 2015 via email

@vincentdu101
Copy link

Yeah we're seeing the same issue as well even with angular ui router. Does anybody have a valid work around for this issue in the meantime?

@viattik
Copy link

viattik commented Jul 31, 2015

Seeing the same issue in uiWebView on latest iOS9.

@raftheunis87
Copy link

Does anyone have any updates on this issue?

@lgalfaso
Copy link
Contributor

lgalfaso commented Aug 3, 2015

This is still an issue. Reopening

@Narretz
Copy link
Contributor

Narretz commented Aug 3, 2015

It looks like an ios issue. Is this tracked on webkit somewhere?

@Narretz Narretz modified the milestones: Ice Box, Backlog Aug 3, 2015
@mike1e
Copy link

mike1e commented Aug 4, 2015

+1

1 similar comment
@RolfDeVries
Copy link

+1

@borrull
Copy link

borrull commented Aug 5, 2015

Same here. Our Cordova app runs fine if running as web on the iPad Safari, but the infinite digest happens if it runs as a Cordova app (UIWebView).

@raftheunis87
Copy link

Exactly the same issues as @borrull ! Already experimented with WKWebView and then the issue is non-existing. But we can't use WKWebView as we need Local File Serving (and we don't want to run a local server in our application) and cookies. So it has to do something with UIWebView in combination with Cordova/Mobile Safari on iOS 9. I'm currently debugging the $locationWatch in Angular because I see that our application wants to transition to a different location multiple times and then (after 10 times) the digest error is thrown.

@alexislg2
Copy link

Does released 1.4.6 fix this issue for good?

@petebacondarwin
Copy link
Member

@alexislg2 - yes this release should fix the issue so you do not need to apply the patch.

@dbroadhurst
Copy link

Confirmed, works for me on the simulator and device, just need my users to wait 2 weeks for Apple approval ;-(

@petebacondarwin
Copy link
Member

@dbroadhurst I heard you might be able to quote the https://openradar.appspot.com/22186109 bug report to fast track your update to your app.

@hober
Copy link

hober commented Sep 21, 2015

You can follow this WebKit bug for updates.

@lchenneberg
Copy link

Hi, you seem to have solved the issue of iOS9 async call on hash change on Angular.js.

I've made researches, also posted on stackoverflow but the only solution I found until now is in your angular browser.js patch.

I'm not really familiar with angular and I would like to understand what you did make you fix available in
every web application based on Hash Routing

Would you explain how you identified and fixed the problem?

http://stackoverflow.com/questions/32719631/how-to-fix-window-location-issue-in-ios9-uiwebview?noredirect=1#comment53359668_32719631

@petebacondarwin
Copy link
Member

@lchenneberg - the commit that fixes the problem in AngularJS is here 8d39bd8

The problem is that this particular browser does not update the value for window.location.href until the next run of the JavaScript event loop. This means that if you write to that value then immediately read it back you get a different value:

console.log(window.location.href)   // -> http://my.domain.com/path/to/page
window.location.href = 'http://my.domain.com/path/to/other/page';
console.log(window.location.href)   // -> http://my.domain.com/path/to/page

// next tick of the event loop

console.log(window.location.href)   // -> http://my.domain.com/path/to/other/page

Notice that the second console.log returns the old value, not the new value. After the current event loop completes, the value is updated, as can be seen in the third console.log

The fix that we have come up with, is to cache the value that we wrote, if the browser is not updating synchronously, and then to use that value from then on, instead of the value returned from window.location.href, until there is a hashchange event, which tells us that the browser has finally sorted itself out.

Hope that helps.

@jasdeepsingh
Copy link

@IgorMinar 's patch worked well for me. I'm using the following versions of Angular & Ionic:

window.ionic.version "1.0.1"
angular.version
Object {full: "1.3.13", major: 1, minor: 3, dot: 13, codeName: "meticulous-riffleshuffle"}

@tpeiffer
Copy link

tpeiffer commented Oct 1, 2015

@IgorMinar's patch worked for us as well. Thanks!!

But I have another question one of you may be able to answer:

does launching a web page added to the iPad home screen open the page using UIWebView or WKWebView?

Or, more importantly, does accessing a web application in this way take advantage of the Nitro rendering engine?

@mhartington
Copy link

@tpeiffer they would use wkwebview, since it's just safari without the address bar.

@tzamora
Copy link

tzamora commented Oct 1, 2015

Hi, I have this exact same issue with an old version of angular: 1.0.6
I see that all the fixes are for newer versions, do you know where should I be looking to see if I can fix this problem? Thanks.

@petebacondarwin
Copy link
Member

@tzamora Have you tried applying @IgorMinar's patch? Perhaps 1.0.6 is too early for it to work.

@tzamora
Copy link

tzamora commented Oct 2, 2015

@petebacondarwin the @IgorMinar's patch refers to a file called browser.js. I dont have any file called browser.js

@hober
Copy link

hober commented Oct 2, 2015

FYI, a fix for the underlying issue landed in WebKit the other day:
http://trac.webkit.org/changeset/190092
http://trac.webkit.org/changeset/190100

@var1ableX
Copy link

I got this working with the js patch, but not straight away. New to this (angularjs and Ionic) so if someone could check this and let me know if I've missed anything major I'd really appreciate it! (e.g. is the platform object very inefficient etc)

Note:

  1. I downloaded the ios9-$browser-patch.js local
  2. I found that it didn't solve my problem, but forcing isIOS9UIWebView to return true, worked great
  3. I rewrote the patch check using Ionic platform methods, which works fine now. (I've left the old code commented here to show the evolution)
function isIOS9UIWebView(userAgent) {
      return (/9\.[0-9]\.[0-9]/.test(ionic.Platform.version()) && /iOS/.test(ionic.Platform.device() ));

      //return true;
      //return (navigator.userAgent.indexOf(' OS 9') != -1) && (navigator.appVersion.indexOf(' OS 9') != -1);
      //return /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
      // only provide the patch for iOS9 on UIWebView
    }

@scott-phillips-sp
Copy link

I ran into this problem on 8.4 on the simulator; so I don't think it's limited to just iOS 9. I just updated the agent string check to include versions iOS 8 & 9. Here's the agent string.

"Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H141 (140307121489296)"

@StevenStar
Copy link

+1

@FreudGit
Copy link

Hi

Can someone confirm if this was solved on ios 9.2? (beta)

Thanks :)

@mrowles
Copy link

mrowles commented Dec 9, 2015

I cannot replicate the issue as of this mornings update to iOS 9.2 (13C75) on iPhone 6. Looking good so far. This bug is still open though - https://openradar.appspot.com/22186109

@kthxboosty
Copy link

If this patch is applied, could it have any negative effect on iOS 9.2 and up? I will test this with our own app, but I want to make sure I'm not introducing issues that don't show when testing our particular situation.

As far as I can see, all the patches use a regex that filters iOS 9 and up, but not specifically 9.x up to and including 9.1.

@ghost
Copy link

ghost commented Dec 21, 2015

Hey guys, this issue is currently happening in iPhone 6 with iOS 9, can anyone let me know why?
https://forum.ionicframework.com/t/ios-9-beta-slide-menu-app-transition-issue/30768
is another patch that I need to apply? Please let me know, I really need to fix that screen overlap issue.

@brechtcs
Copy link

Updating to iOS 9.2 seems to solve it for me too.

@lgalfaso
Copy link
Contributor

@bruno-serfe this is an issue on how iOS handles window.location that is present only in iOS 9.0.x. If you can update to Angular 1.4.6+, then there is nothing else you have to do as this version contains the fix. If you cannot upgrade, then the patch at #12241 (comment) has the same fix.

As stated before, this issue is present only in iOS 9.0.x as this was fixed in iOS 9.1.0.

The issue posted on ionic looks like the same issue, so the same fix should work both ways.

@ghost
Copy link

ghost commented Dec 21, 2015

@lgalfaso thanks for the reply, I'll try to fix a digest error I've found, if that doesn't solve the issue I'll try upgrading angular, thanks for the reply!.

@mrowles
Copy link

mrowles commented Dec 22, 2015

Thanks @lgalfaso 👍

@tjespe
Copy link

tjespe commented Jan 30, 2016

I had this problem when I added the web app to home screen and used it as standalone, however upgrading from AngularJS 1.4.5 to 1.5 completely solved the problem and speeded up the navigation as hell!

@raftheunis87
Copy link

@volgwfang The issue that you're having is not related to this topic?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.