Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(copy): add support for copying Blob objects #14064

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,9 @@ function copy(source, destination) {
var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
re.lastIndex = source.lastIndex;
return re;

case '[object Blob]':
return new source.constructor([source], {type: source.type});
}

if (isFunction(source.cloneNode)) {
Expand Down
12 changes: 12 additions & 0 deletions test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,18 @@ describe('angular', function() {
}
});

it('should handle Blob objects', function() {
if (typeof Blob !== 'undefined') {
var src = new Blob(['foo'], {type: 'bar'});
var dst = copy(src);

expect(dst).not.toBe(src);
expect(dst.size).toBe(3);
expect(dst.type).toBe('bar');
expect(isBlob(dst)).toBe(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked if this test perhaps passes and gives a false positive without the applied copyType() patch?

I seem to recall, when running into this issue first, that the cloned object was getting reported as a Blob even though it was not actually one, and I could only detect the difference by attempting to make a call to one of its specific functions like slice() or by attempting to read the blob's content by using the FileReader interface (either of which then failed in some internal implementation, in different ways depending on the browser used).

Update: I just checked it at http://plnkr.co/edit/xenwdKodooTrYO7VG2P2 and the test is good while my memory was mistaken. 👍 😄 The test will fail on 3 of those expect() calls - size access, type access & the isBlob() check. The thing I recalled incorrectly was that the typeof operator was returning Blob for the cloned object. Good work!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I don't think typeof returns Blob for blobs. In latest Chrome and Firefox at least, it return object.
(Maybe what you had in mind is that expect(typeof dst).toBe(typeof src) would indeed pass even without the fix (because both would return object).)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm certain I got Blob for natively created Blob objects with PhantomJS. Don't recall what actual user browsers gave me there. But it does not matter in the end. Should work like a charm now. 😺

}
});

it("should throw an exception if a Uint8Array is the destination", function() {
if (typeof Uint8Array !== 'undefined') {
var src = new Uint8Array();
Expand Down
20 changes: 20 additions & 0 deletions test/ngMock/angular-mocksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,26 @@ describe('ngMock', function() {
});


it('should be able to handle Blobs as mock data', function() {
if (typeof Blob !== 'undefined') {
var mockBlob = new Blob(['{"foo":"bar"}'], {type: 'application/json'});

hb.when('GET', '/url1').respond(200, mockBlob, {});

callback.andCallFake(function(status, response) {
expect(response).not.toBe(mockBlob);
expect(response.size).toBe(13);
expect(response.type).toBe('application/json');
expect(response.toString()).toBe('[object Blob]');
});

hb('GET', '/url1', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnce();
}
});


it('should throw error when unexpected request', function() {
hb.when('GET', '/url1').respond(200, 'content');
expect(function() {
Expand Down