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), angularWidget = extensionMap(angular, 'widget', shivForIE),
/** @name angular.module.ng */ /** @name angular.module.ng */
angularInputType = extensionMap(angular, 'inputType', lowercase), angularInputType = extensionMap(angular, 'inputType', lowercase),
/** @name angular.module.ng */
angularCallbacks = extensionMap(angular, 'callbacks'),
nodeName_, nodeName_,
uid = ['0', '0', '0'], uid = ['0', '0', '0'],
DATE_ISOSTRING_LN = 24; DATE_ISOSTRING_LN = 24;

View file

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

View file

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

View file

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