Re: Lazy Blob

Hi Glenn,

On Aug 3, 2012, at 01:23 , Glenn Maynard wrote:
> I'd suggest the following.
> 
> - Introduce an interface URLObject (bikeshedding can come later), with no methods.  This object is supported by structured clone.
> - Add XMLHttpRequest.getURLObject(optional data), which returns a new URLObject.  This can only be called while XMLHttpRequest is in the OPENED state.  The returned URLObject represents the resource that would have been fetched if xhr.send() had been called.  No XHR callbacks are performed, and no network activity takes place.  The "data" argument acts like send(data), to specify the request entity body that will be sent.
> - Adjust URL.createObjectURL to take (Blob or URLObject), which returns a URL that works the same way as Blob URLs.
> 
> Example:
> 
> var xhr = new XMLHttpRequest();
> xhr.open("GET", "resource.jpg");
> var urlObject = xhr.getURLObject();
> var newURL = URL.getObjectURL(urlObject);
> img.src = newURL;

I like this idea, but I'm not certain if it differs that much from one of the options I listed (albeit a fair bit less clearly, and in the middle of a shopping list, which could explain why you overlooked it). Quoting:

> === Another XHR Approach
> 
> partial interface XMLHttpRequest {
>    Blob makeLazyBlob ();
> };
> 
> Usage:
> var xhr = new XMLHttpRequest();
> xhr.open("GET", "/kitten.png", true);
> xhr.setRequestHeader("Authorization", "Basic DEADBEEF");
> var blob =xhr.makeLazyBlob();


Unless I missed something, the only differences are the name (which we can bikeshed on later indeed — I certainly am not married to lazy blobs though it would make for a finer insult than URLObject) and that you mint a new object while I reuse Blob. Having mulled this over the weekend, the tradeoffs (assuming that both work the same, i.e. like send() with no eventing, etc.) are:

Using Blob
• It doesn't introduce a new interface;
• Blobs can already be scloned;
• Blobs already work with getObjectURL which means that part needn't change either.
But
• The Blob's |size| attribute cannot be set (without resorting to HEADs, which blows for a bunch of reasons),
• It's a little weird that it seems to duplicate responseType = blob, the primary difference (that developers are likely to ever care about) is that the network request is deferred (or… lazy ;).

I wonder if we could circumvent the |size| issue by allowing Blobs to return null for that (making the type "unsigned long long?"). I understand how Jonas sees this as making it closer to Stream, but I think it's the primary way in which it is. It seems more logical to me to occasionally have to deal with files the size of which you don't know, than to e.g. assign a stream to an <img>.

Frankly I can easily live with either and will be more than happy to bow to implementer preference between the two; what I mostly need is a way of exchanging pointers to remote resources in the way described in the original use cases.

For URLObject, you mention the case of passing it to XHR:

var urlO = getURLObject(); // this comes from a service or something
var newURL = URL.getObjectURL(urlO);
var xhr = new XMLHttpRequest();
xhr.open("GET", newURL, false);
xhr.responseType = "blob";
xhr.send();
var blob = xhr.response;

The ability to get a Blob (rather than just a blob URL) is vitally useful if you wish to store the information, e.g. in an IndexedDB. So long as I can get one, even if it's a bit more convoluted, I'm happy.

> Passing one of these URLs back to XHR would need extra consideration (eg. should you be able to specify more headers?).

I would assume that the request to the blob URL would work just like any request to a blob URL (you can only use GET, setting headers does nothing useful, etc.). None of this would have any effect whatsoever on the XHR from which the URLObject was created (anything else would be a likely attack vector and does not seem useful).

> (Note that I've spent some time thinking about this because I think it's technically interesting, but I haven't looked over the use cases closely enough to say whether I think it'd be worthwhile or not.)

Well, it's an issue that a few of us have bumped into — so I think it's useful :)

-- 
Robin Berjon - http://berjon.com/ - @robinberjon

Received on Monday, 6 August 2012 13:23:52 UTC