Skip to content

Commit 3a74c42

Browse files
fix(): only IE8 and below can't use script.onload for JSONP
IE8, IE9 and IE10 can use `script.onreadystate` so up till now we have been using this if the sniffer says we are on IE. But IE11 now does not support `script.onreadystate` and only supports the more standard `script.onload` and `script.onerror`. IE9 and IE10 do support `script.onload` and `script.onerror`. So now we only test whether we are on IE8 or earlier before using `script.onreadystate`. See http://pieisgood.org/test/script-link-events/ jQuery just uses all these handlers at once and hopes for the best, but since IE9 and IE10 support both sets of handlers, this could cause the handlers to be run more than once. jQuery also notes that there is a potential memory leak in IE unless we remove the handlers from the script object once they are run. So we are doing this too, now. Closes angular#4523 Closes angular#4527 Closes angular#4922
1 parent e33c365 commit 3a74c42

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/ng/httpBackend.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,24 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
128128
// - adds and immediately removes script elements from the document
129129
var script = rawDocument.createElement('script'),
130130
doneWrapper = function() {
131+
script.onreadystatechange = script.onload = script.onerror = null;
131132
rawDocument.body.removeChild(script);
132133
if (done) done();
133134
};
134135

135136
script.type = 'text/javascript';
136137
script.src = url;
137138

138-
if (msie) {
139+
if (msie && msie <= 8) {
139140
script.onreadystatechange = function() {
140-
if (/loaded|complete/.test(script.readyState)) doneWrapper();
141+
if (/loaded|complete/.test(script.readyState)) {
142+
doneWrapper();
143+
}
141144
};
142145
} else {
143-
script.onload = script.onerror = doneWrapper;
146+
script.onload = script.onerror = function() {
147+
doneWrapper();
148+
};
144149
}
145150

146151
rawDocument.body.appendChild(script);

test/ng/httpBackendSpec.js

+35-3
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ describe('$httpBackend', function() {
273273
script.readyState = 'complete';
274274
script.onreadystatechange();
275275
} else {
276-
script.onload()
276+
script.onload();
277277
}
278278

279279
expect(callback).toHaveBeenCalledOnce();
@@ -294,14 +294,46 @@ describe('$httpBackend', function() {
294294
script.readyState = 'complete';
295295
script.onreadystatechange();
296296
} else {
297-
script.onload()
297+
script.onload();
298298
}
299299

300300
expect(callbacks[callbackId]).toBeUndefined();
301301
expect(fakeDocument.body.removeChild).toHaveBeenCalledOnceWith(script);
302302
});
303303

304304

305+
if(msie<=8) {
306+
307+
it('should attach onreadystatechange handler to the script object', function() {
308+
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
309+
310+
expect(fakeDocument.$$scripts[0].onreadystatechange).toEqual(jasmine.any(Function));
311+
312+
var script = fakeDocument.$$scripts[0];
313+
314+
script.readyState = 'complete';
315+
script.onreadystatechange();
316+
317+
expect(script.onreadystatechange).toBe(null);
318+
});
319+
320+
} else {
321+
322+
it('should attach onload and onerror handlers to the script object', function() {
323+
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
324+
325+
expect(fakeDocument.$$scripts[0].onload).toEqual(jasmine.any(Function));
326+
expect(fakeDocument.$$scripts[0].onerror).toEqual(jasmine.any(Function));
327+
328+
var script = fakeDocument.$$scripts[0];
329+
script.onload();
330+
331+
expect(script.onload).toBe(null);
332+
expect(script.onerror).toBe(null);
333+
});
334+
335+
}
336+
305337
it('should call callback with status -2 when script fails to load', function() {
306338
callback.andCallFake(function(status, response) {
307339
expect(status).toBe(-2);
@@ -316,7 +348,7 @@ describe('$httpBackend', function() {
316348
script.readyState = 'complete';
317349
script.onreadystatechange();
318350
} else {
319-
script.onload()
351+
script.onload();
320352
}
321353
expect(callback).toHaveBeenCalledOnce();
322354
});

0 commit comments

Comments
 (0)