aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ng/httpBackend.js59
-rw-r--r--test/ng/httpBackendSpec.js71
2 files changed, 35 insertions, 95 deletions
diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js
index 28107966..9b2d7361 100644
--- a/src/ng/httpBackend.js
+++ b/src/ng/httpBackend.js
@@ -49,16 +49,13 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
var callbackId = '_' + (callbacks.counter++).toString(36);
callbacks[callbackId] = function(data) {
callbacks[callbackId].data = data;
+ callbacks[callbackId].called = true;
};
var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
- function() {
- if (callbacks[callbackId].data) {
- completeRequest(callback, 200, callbacks[callbackId].data);
- } else {
- completeRequest(callback, status || -2);
- }
- callbacks[callbackId] = angular.noop;
+ callbackId, function(status, text) {
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
+ callbacks[callbackId] = noop;
});
} else {
@@ -158,33 +155,39 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
}
};
- function jsonpReq(url, done) {
+ function jsonpReq(url, callbackId, done) {
// we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
// - fetches local scripts via XHR and evals them
// - adds and immediately removes script elements from the document
- var script = rawDocument.createElement('script'),
- doneWrapper = function() {
- script.onreadystatechange = script.onload = script.onerror = null;
- rawDocument.body.removeChild(script);
- if (done) done();
- };
-
- script.type = 'text/javascript';
+ var script = rawDocument.createElement('script'), callback = null;
+ script.type = "text/javascript";
script.src = url;
-
- if (msie && msie <= 8) {
- script.onreadystatechange = function() {
- if (/loaded|complete/.test(script.readyState)) {
- doneWrapper();
+ script.async = true;
+
+ callback = function(event) {
+ removeEventListenerFn(script, "load", callback);
+ removeEventListenerFn(script, "error", callback);
+ rawDocument.body.removeChild(script);
+ script = null;
+ var status = -1;
+ var text = "unknown";
+
+ if (event) {
+ if (event.type === "load" && !callbacks[callbackId].called) {
+ event = { type: "error" };
}
- };
- } else {
- script.onload = script.onerror = function() {
- doneWrapper();
- };
- }
+ text = event.type;
+ status = event.type === "error" ? 404 : 200;
+ }
+
+ if (done) {
+ done(status, text);
+ }
+ };
+ addEventListenerFn(script, "load", callback);
+ addEventListenerFn(script, "error", callback);
rawDocument.body.appendChild(script);
- return doneWrapper;
+ return callback;
}
}
diff --git a/test/ng/httpBackendSpec.js b/test/ng/httpBackendSpec.js
index 5c9cbf58..837fbab9 100644
--- a/test/ng/httpBackendSpec.js
+++ b/test/ng/httpBackendSpec.js
@@ -39,7 +39,8 @@ describe('$httpBackend', function() {
fakeDocument = {
$$scripts: [],
createElement: jasmine.createSpy('createElement').andCallFake(function() {
- return {};
+ // Return a proper script element...
+ return document.createElement(arguments[0]);
}),
body: {
appendChild: jasmine.createSpy('body.appendChild').andCallFake(function(script) {
@@ -325,13 +326,7 @@ describe('$httpBackend', function() {
expect(url[1]).toBe('http://example.org/path');
callbacks[url[2]]('some-data');
-
- if (script.onreadystatechange) {
- script.readyState = 'complete';
- script.onreadystatechange();
- } else {
- script.onload();
- }
+ browserTrigger(script, "load");
expect(callback).toHaveBeenCalledOnce();
});
@@ -346,71 +341,13 @@ describe('$httpBackend', function() {
callbackId = script.src.match(SCRIPT_URL)[2];
callbacks[callbackId]('some-data');
-
- if (script.onreadystatechange) {
- script.readyState = 'complete';
- script.onreadystatechange();
- } else {
- script.onload();
- }
+ browserTrigger(script, "load");
expect(callbacks[callbackId]).toBe(angular.noop);
expect(fakeDocument.body.removeChild).toHaveBeenCalledOnceWith(script);
});
- if(msie<=8) {
-
- it('should attach onreadystatechange handler to the script object', function() {
- $backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
-
- expect(fakeDocument.$$scripts[0].onreadystatechange).toEqual(jasmine.any(Function));
-
- var script = fakeDocument.$$scripts[0];
-
- script.readyState = 'complete';
- script.onreadystatechange();
-
- expect(script.onreadystatechange).toBe(null);
- });
-
- } else {
-
- it('should attach onload and onerror handlers to the script object', function() {
- $backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
-
- expect(fakeDocument.$$scripts[0].onload).toEqual(jasmine.any(Function));
- expect(fakeDocument.$$scripts[0].onerror).toEqual(jasmine.any(Function));
-
- var script = fakeDocument.$$scripts[0];
- script.onload();
-
- expect(script.onload).toBe(null);
- expect(script.onerror).toBe(null);
- });
-
- }
-
- it('should call callback with status -2 when script fails to load', function() {
- callback.andCallFake(function(status, response) {
- expect(status).toBe(-2);
- expect(response).toBeUndefined();
- });
-
- $backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
- expect(fakeDocument.$$scripts.length).toBe(1);
-
- var script = fakeDocument.$$scripts.shift();
- if (script.onreadystatechange) {
- script.readyState = 'complete';
- script.onreadystatechange();
- } else {
- script.onload();
- }
- expect(callback).toHaveBeenCalledOnce();
- });
-
-
it('should set url to current location if not specified or empty string', function() {
$backend('JSONP', undefined, null, callback);
expect(fakeDocument.$$scripts[0].src).toBe($browser.url());