fix(): use angular.callbacks namespace for jsonp callbacks

Previously we used to put callbacks on the window object, but that
causes problems on IE8 where it is not possible to delete properties
from the window object
This commit is contained in:
Igor Minar 2011-12-07 07:53:57 -08:00
parent b9001e9147
commit fd38655e6c
4 changed files with 17 additions and 20 deletions

View file

@ -101,8 +101,6 @@ var $$scope = '$scope',
angularWidget = extensionMap(angular, 'widget', shivForIE),
/** @name angular.module.ng */
angularInputType = extensionMap(angular, 'inputType', lowercase),
/** @name angular.module.ng */
angularCallbacks = extensionMap(angular, 'callbacks'),
nodeName_,
uid = ['0', '0', '0'],
DATE_ISOSTRING_LN = 24;

View file

@ -47,7 +47,8 @@ function publishExternalAPI(angular){
'version': version,
'isDate': isDate,
'lowercase': lowercase,
'uppercase': uppercase
'uppercase': uppercase,
'callbacks': {counter: 0}
});
angularModule.ng = ngModule;

View file

@ -17,31 +17,29 @@ var XHR = window.XMLHttpRequest || function() {
*/
function $HttpBackendProvider() {
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
return createHttpBackend($browser, XHR, $browser.defer, $window, $document[0].body,
$window.location.href.replace(':', ''));
return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,
$document[0].body, $window.location.href.replace(':', ''));
}];
}
function createHttpBackend($browser, XHR, $browserDefer, $window, body, locationProtocol) {
var idCounter = 0;
function createHttpBackend($browser, XHR, $browserDefer, callbacks, body, locationProtocol) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout) {
$browser.$$incOutstandingRequestCount();
if (lowercase(method) == 'jsonp') {
var callbackId = ('angular_' + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
$window[callbackId] = function(data) {
$window[callbackId].data = data;
var callbackId = '_' + (callbacks.counter++).toString(36);
callbacks[callbackId] = function(data) {
callbacks[callbackId].data = data;
};
var script = $browser.addJs(url.replace('JSON_CALLBACK', callbackId), null, function() {
if ($window[callbackId].data) {
completeRequest(callback, 200, $window[callbackId].data);
if (callbacks[callbackId].data) {
completeRequest(callback, 200, callbacks[callbackId].data);
} else {
completeRequest(callback, -2);
}
delete $window[callbackId];
delete callbacks[callbackId];
body.removeChild(script);
});
} else {

View file

@ -1,6 +1,6 @@
describe('$httpBackend', function() {
var $backend, $browser, $window,
var $backend, $browser, callbacks,
xhr, fakeBody, callback;
// TODO(vojta): should be replaced by $defer mock
@ -19,10 +19,10 @@ describe('$httpBackend', function() {
beforeEach(inject(function($injector) {
$window = {};
callbacks = {};
$browser = $injector.get('$browser');
fakeBody = {removeChild: jasmine.createSpy('body.removeChild')};
$backend = createHttpBackend($browser, MockXhr, fakeTimeout, $window, fakeBody);
$backend = createHttpBackend($browser, MockXhr, fakeTimeout, callbacks, fakeBody);
callback = jasmine.createSpy('done');
}));
@ -135,7 +135,7 @@ describe('$httpBackend', function() {
url = script.url.split('?cb=');
expect(url[0]).toBe('http://example.org/path');
$window[url[1]]('some-data');
callbacks[url[1]]('some-data');
script.done();
expect(callback).toHaveBeenCalledOnce();
@ -149,10 +149,10 @@ describe('$httpBackend', function() {
var script = $browser.$$scripts.shift(),
callbackId = script.url.split('?cb=')[1];
$window[callbackId]('some-data');
callbacks[callbackId]('some-data');
script.done();
expect($window[callbackId]).toBeUndefined();
expect(callbacks[callbackId]).toBeUndefined();
expect(fakeBody.removeChild).toHaveBeenCalledOnce();
expect(fakeBody.removeChild).toHaveBeenCalledWith(script);
});