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

Commit cc92da0

Browse files
mgolpetebacondarwin
authored andcommitted
chore(*): cleanup msie handling; add support comments
1. The conditions checking the msie variable value have been simplified. There is e.g. no point to check if `msie <= 11` since there IE 12 won't ever exist. 2. Edge UA-sniffing has been added to tests (only!) where appropriate 3. Support comments for IE/Edge have been added. Closes #15407
1 parent c9bb5b9 commit cc92da0

17 files changed

+62
-21
lines changed

src/Angular.js

+2
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ var
169169
angularModule,
170170
uid = 0;
171171

172+
// Support: IE 9-11 only
172173
/**
173174
* documentMode is an IE-only property
174175
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
@@ -1279,6 +1280,7 @@ function fromJson(json) {
12791280

12801281
var ALL_COLONS = /:/g;
12811282
function timezoneToOffset(timezone, fallback) {
1283+
// Support: IE 9-11 only, Edge 13-14+
12821284
// IE/Edge do not "understand" colon (`:`) in timezone
12831285
timezone = timezone.replace(ALL_COLONS, '');
12841286
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;

src/auto/injector.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,9 @@ function createInjector(modulesToLoad, strictDi) {
849849
}
850850

851851
function isClass(func) {
852+
// Support: IE 9-11 only
852853
// IE 9-11 do not support classes and IE9 leaks with the code below.
853-
if (msie <= 11 || typeof func !== 'function') {
854+
if (msie || typeof func !== 'function') {
854855
return false;
855856
}
856857
var result = func.$$ngIsClass;

src/ng/compile.js

+1
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
19591959
for (var i = 0; i < nodeList.length; i++) {
19601960
attrs = new Attributes();
19611961

1962+
// Support: IE 11 only
19621963
// Workaround for #11781 and #14924
19631964
if (msie === 11) {
19641965
mergeConsecutiveTextNodes(nodeList, i, notLiveList);

src/ng/directive/attrs.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,11 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
426426

427427
attr.$set(name, value);
428428

429-
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
429+
// Support: IE 9-11 only
430+
// On IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
430431
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
431432
// to set the property as well to achieve the desired effect.
432-
// we use attr[attrName] value since $set can sanitize the url.
433+
// We use attr[attrName] value since $set can sanitize the url.
433434
if (msie && propName) element.prop(propName, attr[name]);
434435
});
435436
}

src/ng/rootScope.js

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ function $RootScopeProvider() {
105105

106106
function cleanUpScope($scope) {
107107

108+
// Support: IE 9 only
108109
if (msie === 9) {
109110
// There is a memory leak in IE9 if all child scopes are not disconnected
110111
// completely when a scope is destroyed. So this code will recurse up through

src/ng/sce.js

+1
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ function $SceProvider() {
748748

749749
this.$get = ['$parse', '$sceDelegate', function(
750750
$parse, $sceDelegate) {
751+
// Support: IE 9-11 only
751752
// Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
752753
// the "expression(javascript expression)" syntax which is insecure.
753754
if (enabled && msie < 8) {

src/ng/sniffer.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ function $SnifferProvider() {
5757
// We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
5858
history: !!(hasHistoryPushState && !(android < 4) && !boxee),
5959
hasEvent: function(event) {
60+
// Support: IE 9-11 only
6061
// IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
6162
// it. In particular the event is not fired when backspace or delete key are pressed or
6263
// when cut operation is performed.
6364
// IE10+ implements 'input' event but it erroneously fires under various situations,
6465
// e.g. when placeholder changes, or a form is focused.
65-
if (event === 'input' && msie <= 11) return false;
66+
if (event === 'input' && msie) return false;
6667

6768
if (isUndefined(eventSupport[event])) {
6869
var divElm = document.createElement('div');

src/ng/urlUtils.js

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ var originUrl = urlResolve(window.location.href);
5858
function urlResolve(url) {
5959
var href = url;
6060

61+
// Support: IE 9-11 only
6162
if (msie) {
6263
// Normalize before parse. Refer Implementation Notes on why this is
6364
// done in two steps on IE.

src/ngScenario/dsl.js

+7
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ angular.scenario.dsl('binding', function() {
201201
*/
202202
angular.scenario.dsl('input', function() {
203203
var chain = {};
204+
205+
// Support: IE 9-11 only
206+
// IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
207+
// it. In particular the event is not fired when backspace or delete key are pressed or
208+
// when cut operation is performed.
209+
// IE10+ implements 'input' event but it erroneously fires under various situations,
210+
// e.g. when placeholder changes, or a form is focused.
204211
var supportInputEvent = 'oninput' in window.document.createElement('div') && !msie;
205212

206213
chain.enter = function(value, event) {

test/helpers/matchers.js

+5
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,19 @@ beforeEach(function() {
357357

358358
toBeMarkedAsSelected: function() {
359359
// Selected is special because the element property and attribute reflect each other's state.
360+
361+
// Support: IE 9 only
360362
// IE9 will wrongly report hasAttribute('selected') === true when the property is
361363
// undefined or null, and the dev tools show that no attribute is set
364+
362365
return {
363366
compare: function(actual) {
364367
var errors = [];
365368
if (actual.selected === null || typeof actual.selected === 'undefined' || actual.selected === false) {
366369
errors.push('Expected option property "selected" to be truthy');
367370
}
368371

372+
// Support: IE 9 only
369373
if (msie !== 9 && actual.hasAttribute('selected') === false) {
370374
errors.push('Expected option to have attribute "selected"');
371375
}
@@ -383,6 +387,7 @@ beforeEach(function() {
383387
errors.push('Expected option property "selected" to be falsy');
384388
}
385389

390+
// Support: IE 9 only
386391
if (msie !== 9 && actual.hasAttribute('selected')) {
387392
errors.push('Expected option not to have attribute "selected"');
388393
}

test/ng/compileSpec.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ describe('$compile', function() {
469469
}));
470470

471471
// NOTE: This test may be redundant.
472+
// Support: Edge 14+
473+
// An `<svg>` element inside a `<foreignObject>` element on MS Edge has no
474+
// size, causing the included `<circle>` element to also have no size and thus fails an
475+
// assertion (relying on the element having a non-zero size).
472476
if (!isEdge) {
473477
it('should handle custom svg containers that transclude to foreignObject' +
474478
' that transclude to custom svg containers that transclude to custom elements', inject(function() {
@@ -1127,7 +1131,8 @@ describe('$compile', function() {
11271131
expect(element).toHaveClass('class_2');
11281132
}));
11291133

1130-
if (!msie || msie > 11) {
1134+
// Support: IE 9-11 only
1135+
if (!msie) {
11311136
// style interpolation not working on IE (including IE11).
11321137
it('should handle interpolated css style from replacing directive', inject(
11331138
function($compile, $rootScope) {
@@ -10698,6 +10703,8 @@ describe('$compile', function() {
1069810703
expect(element.text()).toBe('102030');
1069910704
expect(newWatcherCount).toBe(3);
1070010705

10706+
// Support: IE 11 only
10707+
// See #11781 and #14924
1070110708
if (msie === 11) {
1070210709
expect(element.find('ng-transclude').contents().length).toBe(1);
1070310710
}
@@ -10719,9 +10726,10 @@ describe('$compile', function() {
1071910726
expect(element.attr('src')).toEqual('http://example.com/image2.png');
1072010727
}));
1072110728

10729+
// Support: IE 9 only
1072210730
// IE9 rejects the video / audio tag with "Error: Not implemented" and the source tag with
1072310731
// "Unable to get value of the property 'childNodes': object is null or undefined"
10724-
if (!msie || msie > 9) {
10732+
if (msie !== 9) {
1072510733
they('should NOT require trusted values for $prop src', ['video', 'audio'],
1072610734
function(tag) {
1072710735
inject(function($rootScope, $compile, $sce) {
@@ -11154,7 +11162,9 @@ describe('$compile', function() {
1115411162
}));
1115511163
});
1115611164

11157-
if (!msie || msie >= 11) {
11165+
// Support: IE 9-10 only
11166+
// IEs <11 don't support srcdoc
11167+
if (!msie || msie === 11) {
1115811168
describe('iframe[srcdoc]', function() {
1115911169
it('should NOT set iframe contents for untrusted values', inject(function($compile, $rootScope, $sce) {
1116011170
element = $compile('<iframe srcdoc="{{html}}"></iframe>')($rootScope);

test/ng/directive/booleanAttrsSpec.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ describe('ngSrc', function() {
182182
}));
183183

184184

185+
// Support: IE 9-11 only
185186
if (msie) {
186187
it('should update the element property as well as the attribute', inject(
187188
function($compile, $rootScope, $sce) {
@@ -283,8 +284,9 @@ describe('ngHref', function() {
283284
expect(element.attr('href')).toEqual(undefined);
284285
}));
285286

286-
if (msie) {
287-
// IE11/10/Edge fail when setting a href to a URL containing a % that isn't a valid escape sequence
287+
// Support: IE 9-11 only, Edge 12-14+
288+
if (msie || /\bEdge\/[\d\.]+\b/.test(window.navigator.userAgent)) {
289+
// IE/Edge fail when setting a href to a URL containing a % that isn't a valid escape sequence
288290
// See https://github.com/angular/angular.js/issues/13388
289291
it('should throw error if ng-href contains a non-escaped percent symbol', inject(function($rootScope, $compile) {
290292
element = $compile('<a ng-href="http://www.google.com/{{\'a%link\'}}">')($rootScope);

test/ng/directive/inputSpec.js

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ describe('input', function() {
135135

136136

137137
describe('IE placeholder input events', function() {
138+
// Support: IE 9-11 only
138139
//IE fires an input event whenever a placeholder visually changes, essentially treating it as a value
139140
//Events:
140141
// placeholder attribute change: *input*

test/ng/locationSpec.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ describe('$location', function() {
3939
/* global urlParsingNode: true */
4040
var urlParsingNodePlaceholder;
4141

42-
beforeEach(inject(function($sniffer) {
43-
if (msie) return;
42+
beforeEach(function() {
43+
// Support: non-Windows browsers
44+
// These tests expect a Windows environment which we can only guarantee
45+
// on IE & Edge.
46+
if (msie || /\bEdge\/[\d\.]+\b/.test(window.navigator.userAgent)) return;
4447

4548
urlParsingNodePlaceholder = urlParsingNode;
4649

@@ -57,13 +60,14 @@ describe('$location', function() {
5760
search: '',
5861
setAttribute: angular.noop
5962
};
60-
}));
63+
});
6164

62-
afterEach(inject(function($sniffer) {
63-
if (msie) return;
65+
afterEach(function() {
66+
// Support: non-Windows browsers
67+
if (msie || /\bEdge\/[\d\.]+\b/.test(window.navigator.userAgent)) return;
6468
//reset urlParsingNode
6569
urlParsingNode = urlParsingNodePlaceholder;
66-
}));
70+
});
6771

6872

6973
it('should not include the drive name in path() on WIN', function() {

test/ng/parseSpec.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2180,8 +2180,9 @@ describe('parser', function() {
21802180
expect(scope.$eval('getter()()')).toBe(33);
21812181
});
21822182

2183+
// Support: IE 9 only
21832184
// There is no "strict mode" in IE9
2184-
if (!msie || msie > 9) {
2185+
if (msie !== 9) {
21852186
it('should set no context to functions returned by other functions', function() {
21862187
scope.getter = function() { return function() { expect(this).toBeUndefined(); }; };
21872188
scope.$eval('getter()()');

test/ng/rootScopeSpec.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ describe('Scope', function() {
1313

1414

1515
it('should expose the constructor', inject(function($rootScope) {
16-
if (msie < 11) return;
17-
// eslint-disable-next-line no-proto
18-
expect($rootScope.__proto__).toBe($rootScope.constructor.prototype);
16+
expect(Object.getPrototypeOf($rootScope)).toBe($rootScope.constructor.prototype);
1917
}));
2018

2119

@@ -125,7 +123,9 @@ describe('Scope', function() {
125123
function Listener() {
126124
expect(this).toBeUndefined();
127125
}
128-
if (msie < 10) return;
126+
// Support: IE 9 only
127+
// IE 9 doesn't support strict mode so its `this` will always be defined.
128+
if (msie === 9) return;
129129
$rootScope.$watch(Getter, Listener);
130130
$rootScope.$digest();
131131
}));
@@ -1227,6 +1227,7 @@ describe('Scope', function() {
12271227
}));
12281228

12291229

1230+
// Support: IE 9 only
12301231
if (msie === 9) {
12311232
// See issue https://github.com/angular/angular.js/issues/10706
12321233
it('should completely disconnect all child scopes on IE9', inject(function($rootScope) {

test/ng/snifferSpec.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,12 @@ describe('$sniffer', function() {
153153

154154

155155
it('should claim that IE9 doesn\'t have support for "oninput"', function() {
156+
// Support: IE 9-11 only
156157
// IE9 implementation is fubared, so it's better to pretend that it doesn't have the support
157158
// IE10+ implementation is fubared when mixed with placeholders
158159
mockDivElement = {oninput: noop};
159160

160-
expect($sniffer.hasEvent('input')).toBe(!(msie && msie <= 11));
161+
expect($sniffer.hasEvent('input')).toBe(!msie);
161162
});
162163
});
163164

0 commit comments

Comments
 (0)