Skip to content

Commit 5245211

Browse files
Merge pull request #109 from angular/master
Update upstream
2 parents 382489b + c133ef8 commit 5245211

File tree

9 files changed

+140
-6
lines changed

9 files changed

+140
-6
lines changed

src/Angular.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1695,8 +1695,13 @@ function angularInit(element, bootstrap) {
16951695
});
16961696
if (appElement) {
16971697
if (!isAutoBootstrapAllowed) {
1698-
window.console.error('AngularJS: disabling automatic bootstrap. <script> protocol indicates ' +
1698+
try {
1699+
window.console.error('AngularJS: disabling automatic bootstrap. <script> protocol indicates ' +
16991700
'an extension, document.location.href does not match.');
1701+
} catch (e) {
1702+
// Support: Safari 11 w/ Webdriver
1703+
// The console.error will throw and make the test fail
1704+
}
17001705
return;
17011706
}
17021707
config.strictDi = getNgAttribute(appElement, 'strict-di') !== null;

src/apis.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,10 @@ function NgMapShim() {
4545
}
4646
NgMapShim.prototype = {
4747
_idx: function(key) {
48-
if (key === this._lastKey) {
49-
return this._lastIndex;
48+
if (key !== this._lastKey) {
49+
this._lastKey = key;
50+
this._lastIndex = this._keys.indexOf(key);
5051
}
51-
this._lastKey = key;
52-
this._lastIndex = this._keys.indexOf(key);
5352
return this._lastIndex;
5453
},
5554
_transformKey: function(key) {
@@ -62,6 +61,11 @@ NgMapShim.prototype = {
6261
return this._values[idx];
6362
}
6463
},
64+
has: function(key) {
65+
key = this._transformKey(key);
66+
var idx = this._idx(key);
67+
return idx !== -1;
68+
},
6569
set: function(key, value) {
6670
key = this._transformKey(key);
6771
var idx = this._idx(key);

src/ng/compile.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2960,7 +2960,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
29602960

29612961
if (!value) {
29622962
var dataName = '$' + name + 'Controller';
2963-
value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
2963+
2964+
if (inheritType === '^^' && $element[0] && $element[0].nodeType === NODE_TYPE_DOCUMENT) {
2965+
// inheritedData() uses the documentElement when it finds the document, so we would
2966+
// require from the element itself.
2967+
value = null;
2968+
} else {
2969+
value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
2970+
}
29642971
}
29652972

29662973
if (!value && !optional) {

src/ngAnimate/animateQueue.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
120120
var disabledElementsLookup = new $$Map();
121121
var animationsEnabled = null;
122122

123+
function removeFromDisabledElementsLookup(evt) {
124+
disabledElementsLookup.delete(evt.target);
125+
}
126+
123127
function postDigestTaskFactory() {
124128
var postDigestCalled = false;
125129
return function(fn) {
@@ -303,6 +307,11 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
303307
bool = !disabledElementsLookup.get(node);
304308
} else {
305309
// (element, bool) - Element setter
310+
if (!disabledElementsLookup.has(node)) {
311+
// The element is added to the map for the first time.
312+
// Create a listener to remove it on `$destroy` (to avoid memory leak).
313+
jqLite(element).on('$destroy', removeFromDisabledElementsLookup);
314+
}
306315
disabledElementsLookup.set(node, !bool);
307316
}
308317
}

test/ApiSpecs.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,34 @@ describe('api', function() {
8989
expect(map.get(keys[2])).toBe(values[2]);
9090
});
9191

92+
it('should return if a key exists or not', function() {
93+
var map = new NgMapShim();
94+
var keys = ['foo', {}];
95+
96+
expect(map.has(keys[0])).toBe(false);
97+
expect(map.has(keys[1])).toBe(false);
98+
99+
map.set(keys[0], 'bar');
100+
expect(map.has(keys[0])).toBe(true);
101+
expect(map.has(keys[1])).toBe(false);
102+
103+
map.set(keys[1], 'baz');
104+
expect(map.has(keys[0])).toBe(true);
105+
expect(map.has(keys[1])).toBe(true);
106+
107+
map.delete(keys[0]);
108+
expect(map.has(keys[0])).toBe(false);
109+
expect(map.has(keys[1])).toBe(true);
110+
111+
map.delete(keys[1]);
112+
expect(map.has(keys[0])).toBe(false);
113+
expect(map.has(keys[1])).toBe(false);
114+
115+
map.set(keys[1], 'qux');
116+
expect(map.has(keys[0])).toBe(false);
117+
expect(map.has(keys[1])).toBe(true);
118+
});
119+
92120
it('should be able to deal with `NaN` keys', function() {
93121
var map = new NgMapShim();
94122

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE html>
2+
<html ng-app="test" require-directive require-target-directive>
3+
<body>
4+
<div id="container"></div>
5+
<script src="angular.js"></script>
6+
<script src="script.js"></script>
7+
</body>
8+
</html>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
3+
angular.
4+
module('test', []).
5+
provider('$exceptionHandler', /** @this */ function() {
6+
this.$get = [function() {
7+
return function(error) {
8+
window.document.querySelector('#container').textContent = error && error.message;
9+
};
10+
}];
11+
}).
12+
13+
directive('requireDirective', function() {
14+
return {
15+
require: '^^requireTargetDirective',
16+
link: function(scope, element, attrs, ctrl) {
17+
window.document.querySelector('#container').textContent = ctrl.content;
18+
}
19+
};
20+
}).
21+
directive('requireTargetDirective', function() {
22+
return {
23+
controller: function() {
24+
this.content = 'requiredContent';
25+
}
26+
};
27+
});
28+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
describe('require parent controller on html element', function() {
4+
it('should not use the html element as the parent element', function() {
5+
6+
loadFixture('directive-require-html');
7+
8+
expect(element(by.id('container')).getText()).toContain('Controller \'requireTargetDirective\', required by directive \'requireDirective\', can\'t be found!');
9+
});
10+
});

test/ngAnimate/animateSpec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,41 @@ describe('animations', function() {
577577
$rootScope.$digest();
578578
expect(capturedAnimation).toBeTruthy();
579579
}));
580+
581+
it('should remove the element from the `disabledElementsLookup` map on `$destroy`',
582+
inject(function($$Map, $animate, $rootScope) {
583+
584+
var setSpy = spyOn($$Map.prototype, 'set').and.callThrough();
585+
var deleteSpy = spyOn($$Map.prototype, 'delete').and.callThrough();
586+
587+
parent.append(element);
588+
589+
$animate.enabled(element, false);
590+
$animate.enabled(element, true);
591+
$animate.enabled(element, false);
592+
expect(setSpy).toHaveBeenCalledWith(element[0], jasmine.any(Boolean));
593+
expect(deleteSpy).not.toHaveBeenCalledWith(element[0]);
594+
expect($animate.enabled(element)).toBe(false);
595+
596+
// No clean-up on `detach` (no `$destroy` event).
597+
element.detach();
598+
expect(deleteSpy).not.toHaveBeenCalledWith(element[0]);
599+
expect($animate.enabled(element)).toBe(false);
600+
601+
// Clean-up on `remove` (causes `$destroy` event).
602+
element.remove();
603+
expect(deleteSpy).toHaveBeenCalledOnceWith(element[0]);
604+
expect($animate.enabled(element)).toBe(true);
605+
606+
deleteSpy.calls.reset();
607+
608+
element.triggerHandler('$destroy');
609+
expect(deleteSpy).not.toHaveBeenCalledWith(element[0]);
610+
611+
$animate.enabled(element, true);
612+
element.triggerHandler('$destroy');
613+
expect(deleteSpy).toHaveBeenCalledOnceWith(element[0]);
614+
}));
580615
});
581616

582617
it('should strip all comment nodes from the animation and not issue an animation if not real elements are found',

0 commit comments

Comments
 (0)