Skip to content

Commit 64da1da

Browse files
martinsikthePunderWoman
authored andcommitted
fix(common): canceled JSONP requests won't throw console error with missing callback function (#36807)
This commit fixes a use-case where unsubscribing from a JSONP request will result in "Uncaught ReferenceError: ng_jsonp_callback_xy is not defined" thrown into console. Unsubscribing won't remove its associated callback function because the requested script will finish loading anyway and will try to call the handler. PR Close #34818 PR Close #36807
1 parent d388522 commit 64da1da

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

packages/common/http/src/jsonp.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,17 @@ export class JsonpClientBackend implements HttpBackend {
125125
// cleanup() is a utility closure that removes the <script> from the page and
126126
// the response callback from the window. This logic is used in both the
127127
// success, error, and cancellation paths, so it's extracted out for convenience.
128-
const cleanup = () => {
128+
const cleanup = (removeCallback = true) => {
129129
// Remove the <script> tag if it's still on the page.
130130
if (node.parentNode) {
131131
node.parentNode.removeChild(node);
132132
}
133133

134-
// Remove the response callback from the callbackMap (window object in the
135-
// browser).
136-
delete this.callbackMap[callback];
134+
if (removeCallback) {
135+
// Remove the response callback from the callbackMap (window object in the
136+
// browser).
137+
delete this.callbackMap[callback];
138+
}
137139
};
138140

139141
// onLoad() is the success callback which runs after the response callback
@@ -218,7 +220,9 @@ export class JsonpClientBackend implements HttpBackend {
218220
node.removeEventListener('error', onError);
219221

220222
// And finally, clean up the page.
221-
cleanup();
223+
// Unsubscription won't remove the callback handler because there's no way to stop
224+
// loading <script> once it has been added to DOM.
225+
cleanup(false);
222226
};
223227
});
224228
}

packages/common/http/test/jsonp_spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ function runOnlyCallback(home: any, data: Object) {
1717
const keys = Object.keys(home);
1818
expect(keys.length).toBe(1);
1919
const callback = home[keys[0]];
20-
delete home[keys[0]];
2120
callback(data);
2221
}
2322

@@ -63,6 +62,11 @@ const SAMPLE_REQ = new HttpRequest<never>('JSONP', '/test');
6362
});
6463
document.mockError(error);
6564
});
65+
it('allows the callback to be invoked when the request is cancelled', () => {
66+
backend.handle(SAMPLE_REQ).subscribe().unsubscribe();
67+
runOnlyCallback(home, {data: 'This is a test'});
68+
expect(Object.keys(home).length).toBe(0);
69+
});
6670
describe('throws an error', () => {
6771
it('when request method is not JSONP',
6872
() => expect(() => backend.handle(SAMPLE_REQ.clone<never>({method: 'GET'})))

0 commit comments

Comments
 (0)