Bug in forEach on chrome #11158
Description
This is a bit of an odd bug that's occurred for me in two instances, one I've managed to fix, the other I can't really fix bar hacking into the forEach code in angularjs.
Basically the forEach is also iterating over the "$$hashMap" key which can cause errors in certain situations. I've seen this happen on Chrome at least, but I haven't tested the other browsers to see if it's browser relevant or not.
Issue 1
The first I managed to solve, it occurred in some custom validation code where I had created a directive to dynamically provide a validation object and have it apply onto an ng-Models $validation code.
Because this was used in a scope I guess it added in the $$hashMap key to the object I was assigning to the $validators object and cause a TypeError: string is not a function
error when the forEach tried to eval the $$hashMap as a key. Code below (simplified a bit):
directive('ngValidation', function() {
return {
restrict: 'A',
require: ['ngModel', '^form'],
link: function(scope, element, attrs, ctrls) {
var ngForm, ngModel, _funcs;
ngModel = ctrls[0], ngForm = ctrls[1];
if ((_funcs = scope.$eval(attrs.ngValidation)) != null) {
if (_funcs.$validators) {
angular.extend(ngModel.$validators, _funcs.$validators);
}
if (_funcs.$asyncValidators) {
angular.extend(ngModel.$asyncValidators, _funcs.$asyncValidators);
}
delete ngModel.$validators.$$hashKey;
delete ngModel.$asyncValidators.$$hashKey;
}
scope.$watch(attrs.ngModel, ngModel.$validate, true);
return ngForm.$addControl(ngModel);
}
};
});
Issue 2
I figure this is the same issue as angular is trying to load a provider called "object:241", which is not defined/requested anywhere in my code and looks very much like a $$hashKey
value.
Error: [$injector:unpr] Unknown provider: object:241Provider <- object:241
http://errors.angularjs.org/1.3.13/$injector/unpr?p0=object%3A241Provider%20%3C-%20object%3A241
at https://crm-node:3443/assets/angular/angular.js?body=1:63:12
at https://crm-node:3443/assets/angular/angular.js?body=1:3997:19
at Object.getService [as get] (https://crm-node:3443/assets/angular/angular.js?body=1:4144:39)
at https://crm-node:3443/assets/angular/angular.js?body=1:4002:45
at Object.getService [as get] (https://crm-node:3443/assets/angular/angular.js?body=1:4144:39)
at https://crm-node:3443/assets/angular-route/angular-route.js?body=1:586:31
at Object.forEach (https://crm-node:3443/assets/angular/angular.js?body=1:331:20)
at https://crm-node:3443/assets/angular-route/angular-route.js?body=1:584:23
at processQueue (https://crm-node:3443/assets/angular/angular.js?body=1:13189:27)
at https://crm-node:3443/assets/angular/angular.js?body=1:13205:27
I think this is caused by the following code (simplified down again):
TicketControllers = angular.module('tickets', [], [
'$routeProvider', '$locationProvider', 'EditControllerResolve', function($routeProvider, $locationProvider, EditControllerResolve) {
$routeProvider.when('/:ticketID', {
templateUrl: '/ticket-partials/edit',
controller: 'EditController',
resolve: EditControllerResolve
});
return $locationProvider.html5Mode(true);
}
]);
TicketControllers.constant('EditControllerResolve', {
ticket: [
'$http', '$q', function($http, $q) {
var deferred;
deferred = $q.defer();
$http.get("/...").success(function(data) {
return deferred.resolve(data);
});
return deferred.promise;
}
],
metadata: [
'$htttp', '$q', '$route', function($http, $q, $route) {
var deferred;
deferred = $q.defer();
$http.get("/...").success(function(data) {
return deferred.resolve(data);
});
return deferred.promise;
}
]
});
TicketControllers.controller('EditController', [function($scope) { ...