Intent to Ship: Canvas.toBlob

158 views
Skip to first unread message

Olivia

unread,
Dec 2, 2015, 8:57:24 PM12/2/15
to blink-dev

Contact emails

xl...@chromium.org


Spec

https://html.spec.whatwg.org/multipage/scripting.html#dom-canvas-toblob


Summary

Creates a Blob object representing a file containing the image in the canvas, and invokes a callback with a handle to that object. Currently, we support three types of image formats--PNG, JPEG and WEBP--just like what toDataURL does. If the file type is not specified, default image format is "image/png".


Link to “Intent to Implement” blink-dev discussion

https://groups.google.com/a/chromium.org/forum/#!searchin/blink-dev/HTMLCanvasElement$20toBlob/blink-dev/Po18IwhHJDM/qKb9OXdxDgAJ


Is this feature supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?

Yes.


Demo link

No demos. But at this moment, developers can turn on experimental canvas features flag in browser to try the feature.


Debuggability

This feature does not require special debugging support on its own.


Interoperability and Compatibility Risk

Interoperability risk is low, as other browsers have already supported this function. Firefox has released this feature in version 19 (https://developer.mozilla.org/en-US/Firefox/Releases/19) and Internet Explorer has the same feature (supporting only PNG image format) with vendor-prefixed name (https://msdn.microsoft.com/en-us/library/windows/apps/hh465735.aspx). Other browsers have no public signals yet.

Compatibility risk is low, as this does not remove or change existing features.


OWP launch tracking bug

http://crbug.com/67587


Entry on the feature dashboard

https://www.chromestatus.com/features/4562033294966784


Philip Jägenstedt

unread,
Dec 3, 2015, 8:59:34 AM12/3/15
to Olivia, blink-dev
Comparing this to Gecko's IDL, I noticed that their callback is not nullable. That makes much more sense, so I've fixed the spec: https://github.com/whatwg/html/pull/377

It's really unfortunate this this API doesn't use promises, but it was added to the spec in 2011, so it is what it is.

LGTM1 to ship with the nullability issue fixed.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

PhistucK

unread,
Dec 3, 2015, 9:08:59 AM12/3/15
to Philip Jägenstedt, Olivia, blink-dev
But exactly because it is not nullable (and shipping), it makes it a candidate for a Promise based alternative.


PhistucK

PhistucK

unread,
Dec 3, 2015, 9:37:37 AM12/3/15
to Philip Jägenstedt, Olivia, blink-dev
Scratch that - I forgot it had an optional parameter (or even more than one) beside that non nullable parameter, which apparently makes the transition impossible in WebIDL (like we discussed in the legacy RTCPeerConnection deprecation thread).


PhistucK

Rick Byers

unread,
Dec 3, 2015, 9:38:27 AM12/3/15
to PhistucK, Philip Jägenstedt, Olivia, blink-dev
LGMT2 (again with nullability fixed).

I find the distinction between Blob and File in the spec to be sloppy and potentially a source of interop issues, so I filed this spec issue.  But that doesn't need to block shipping.

Rick

Boris Zbarsky

unread,
Dec 3, 2015, 9:45:49 AM12/3/15
to blink-dev
On 12/3/15 9:36 AM, PhistucK wrote:
> Scratch that - I forgot it had an optional parameter (or even more than
> one) beside that non nullable parameter, which apparently makes the
> transition impossible in WebIDL (like we discussed in the legacy
> RTCPeerConnection deprecation thread).

Wait, why? This is a perfectly valid overload per IDL:

Promise<void> toBlob(FileCallback _callback,
optional DOMString type = "",
optional any encoderOptions);
Promise<Blob> toBlob(optional DOMString type = "",
optional any encoderOptions);

A call with no arguments selects the second overload since that's the
only valid overload for that number of arguments. A call with one or
more arguments has to distinguish between the two first-argument types,
which are a callback and DOMString. Those are distinguishable, so there
is no problem.

The RTCPeerConnection issue was because the first argument of the
non-callback version is a dictionary, and dictionaries are currently not
distinguishable from callbacks in IDL. It had nothing to do with
optional arguments per se, except insofar as their existence meant that
there was a situation for which an overload could not be selected
unambiguously based on the number of arguments alone and hence
distinguishability entered the picture _and_ the two types involved were
not distinguishable.

-Boris

Noel Gordon

unread,
Dec 3, 2015, 9:48:01 AM12/3/15
to Philip Jägenstedt, Olivia, blink-dev
On 4 December 2015 at 00:59, Philip Jägenstedt <phi...@opera.com> wrote:
Comparing this to Gecko's IDL, I noticed that their callback is not nullable. That makes much more sense, so I've fixed the spec: https://github.com/whatwg/html/pull/377

What does Gekco do with <canvas>.toBlob(42) btw ?  The first argument could be anything. The spec algorithm steps say.

6. If callback is null, abort these steps.

 
It's really unfortunate this this API doesn't use promises, but it was added to the spec in 2011, so it is what it is.

Olivia already mentioned (in bug) that promise based API version is planned.   

~noel

PhistucK

unread,
Dec 3, 2015, 9:54:47 AM12/3/15
to Boris Zbarsky, blink-dev
I get it now. Thank you for the clarification!

So it could be turned into a Promise based API! :) Like Noel mentioned, this is apparently planned. Perhaps Blink could speed it up (not in a "quick and dirty" or "we ship it to force others to do it" way) and ship it.


PhistucK

Justin Novosad

unread,
Dec 3, 2015, 9:55:08 AM12/3/15
to Noel Gordon, Philip Jägenstedt, Olivia, blink-dev
The tentative OffscreenCanvas proposal (https://wiki.whatwg.org/wiki/OffscreenCanvas) calls for just a promise based version of toBlob on the OffscreenCanvas interface.
I think it makes sense to have a similar promise based version on HTMLCanvasElement, for consistency, and the callback version makes sense for compatibility.

I am not sure what this means in terms of "Compatibility risk" for this feature.

    -Justin

Philip Jägenstedt

unread,
Dec 3, 2015, 9:55:43 AM12/3/15
to Noel Gordon, Olivia, blink-dev
On Thu, Dec 3, 2015 at 3:47 PM, Noel Gordon <no...@chromium.org> wrote:
On 4 December 2015 at 00:59, Philip Jägenstedt <phi...@opera.com> wrote:
Comparing this to Gecko's IDL, I noticed that their callback is not nullable. That makes much more sense, so I've fixed the spec: https://github.com/whatwg/html/pull/377

What does Gekco do with <canvas>.toBlob(42) btw ?  The first argument could be anything. The spec algorithm steps say.

6. If callback is null, abort these steps.

It throws a TypeError, just like for null, {}, NaN and other non-function values. I removed the "If callback is null" step from the spec, because it's dead code with the argument non-nullable in the WebIDL definition.

It's really unfortunate this this API doesn't use promises, but it was added to the spec in 2011, so it is what it is.

Olivia already mentioned (in bug) that promise based API version is planned.

That's great, looking forward to see that!

Domenic Denicola

unread,
Dec 3, 2015, 10:11:23 AM12/3/15
to Olivia, blink-dev

I don’t understand our shipping strategy here with respect to promises vs. callbacks.

 

As Philip mentioned, the callback version exists only as a legacy, and the promise version is the future.

 

But why even implement the callback version at all? It is implemented (unprefixed) in one browser. Developers cannot write cross-browser code using toBlob(callback) today. That surely doesn’t make it a part of the web platform that we want to support.

 

We should instead take this opportunity to implement only the promise version. Maybe with a different name, if we are worried about Gecko compatibility, since apparently they don’t implement the promise version yet (looking at https://mxr.mozilla.org/mozilla-central/source/dom/webidl/HTMLCanvasElement.webidl).

 

I don’t think we should ship the current implementation.

Philip Jägenstedt

unread,
Dec 3, 2015, 10:30:31 AM12/3/15
to Domenic Denicola, Olivia, blink-dev
When Blink is the second engine to ship a feature, it will always be true that "developers cannot write cross-browser code," but interop with the existing implementation is still worth something. I don't know exactly how to weigh this, but if you can get the relevant Gecko developers on board with shipping a promise-based toBlob and removing their existing toBlob, that seems OK. If, on the other hand, the response is "that sounds nice maybe we'll fix it some day" then I'm not sure it's worth trying to avoid the callback variant.

Noel Gordon

unread,
Dec 3, 2015, 10:30:48 AM12/3/15
to Rick Byers, PhistucK, Philip Jägenstedt, Olivia, blink-dev
On 4 December 2015 at 01:38, Rick Byers <rby...@chromium.org> wrote:

I find the distinction between Blob and File in the spec to be sloppy and potentially a source of interop issues, so I filed this spec issue.  But that doesn't need to block shipping.

 void toBlob(FileCallback? _callback, optional DOMString type, any... arguments);

The FileCallback confused me when we wrote it.  Why not BlobCallback?  I recall the answer was along the lines of  ... "because it's not needed since, due of this relationship

interface File : Blob { ... }
a FileCallback happily accepts a Blob argument."

I assumed Hixie knew what he was talking about, and I quibbled no more.

For compat, I think we should should be returning a Blob.

~noel


Philip Jägenstedt

unread,
Dec 3, 2015, 10:37:48 AM12/3/15
to Noel Gordon, Rick Byers, PhistucK, Olivia, blink-dev
Given that FileCallback is under "Common DOM interfaces" the ideas was probably that it might get used in other contexts. That didn't happen, so if we stick with the callback variant I'd like to change it to BlobCallback in the spec.

And, yes, we should create a Blob, since that's what Gecko does and what the API name suggests.

Philip

Rick Byers

unread,
Dec 3, 2015, 10:52:30 AM12/3/15
to Philip Jägenstedt, Noel Gordon, PhistucK, Olivia, blink-dev
On Thu, Dec 3, 2015 at 10:37 AM, Philip Jägenstedt <phi...@opera.com> wrote:
On Thu, Dec 3, 2015 at 4:30 PM, Noel Gordon <no...@chromium.org> wrote:

On 4 December 2015 at 01:38, Rick Byers <rby...@chromium.org> wrote:

I find the distinction between Blob and File in the spec to be sloppy and potentially a source of interop issues, so I filed this spec issue.  But that doesn't need to block shipping.

 void toBlob(FileCallback? _callback, optional DOMString type, any... arguments);

The FileCallback confused me when we wrote it.  Why not BlobCallback?  I recall the answer was along the lines of  ... "because it's not needed since, due of this relationship

interface File : Blob { ... }
a FileCallback happily accepts a Blob argument."

I assumed Hixie knew what he was talking about, and I quibbled no more.

For compat, I think we should should be returning a Blob.

Yep this is exactly the spec issue I mentioned above, let's keep the debate there...

Rick Byers

unread,
Dec 3, 2015, 10:59:04 AM12/3/15
to Domenic Denicola, Olivia, blink-dev
On Thu, Dec 3, 2015 at 10:11 AM, Domenic Denicola <d...@domenic.me> wrote:

I don’t understand our shipping strategy here with respect to promises vs. callbacks.

 

As Philip mentioned, the callback version exists only as a legacy, and the promise version is the future.

 

But why even implement the callback version at all? It is implemented (unprefixed) in one browser. Developers cannot write cross-browser code using toBlob(callback) today. That surely doesn’t make it a part of the web platform that we want to support.

 

We should instead take this opportunity to implement only the promise version. Maybe with a different name, if we are worried about Gecko compatibility, since apparently they don’t implement the promise version yet (looking at https://mxr.mozilla.org/mozilla-central/source/dom/webidl/HTMLCanvasElement.webidl).

 

I don’t think we should ship the current implementation.


I think there's a good debate to be had here, but I wouldn't want to block this intent-to-ship for long on this ("intent to implement" would have been a much better time for this debate).  If someone wants to get a promise-based version added to the spec ASAP, and if Mozilla shows interest in implementing it sometime soon, then I'd personally support shipping only the promise based API and not the legacy callback-based API.  Otherwise I'm fine getting caught up to Mozilla first by shipping the existing API, and worrying about adding a promised based API as a follow-up step.

Domenic Denicola

unread,
Dec 3, 2015, 11:06:56 AM12/3/15
to blink-dev, d...@domenic.me, xl...@chromium.org, kh...@mozilla.com


On Thursday, December 3, 2015 at 10:59:04 AM UTC-5, Rick Byers wrote:
On Thu, Dec 3, 2015 at 10:11 AM, Domenic Denicola <d...@domenic.me> wrote:

I don’t understand our shipping strategy here with respect to promises vs. callbacks.

 

As Philip mentioned, the callback version exists only as a legacy, and the promise version is the future.

 

But why even implement the callback version at all? It is implemented (unprefixed) in one browser. Developers cannot write cross-browser code using toBlob(callback) today. That surely doesn’t make it a part of the web platform that we want to support.

 

We should instead take this opportunity to implement only the promise version. Maybe with a different name, if we are worried about Gecko compatibility, since apparently they don’t implement the promise version yet (looking at https://mxr.mozilla.org/mozilla-central/source/dom/webidl/HTMLCanvasElement.webidl).

 

I don’t think we should ship the current implementation.


I think there's a good debate to be had here, but I wouldn't want to block this intent-to-ship for long on this ("intent to implement" would have been a much better time for this debate).  If someone wants to get a promise-based version added to the spec ASAP, and if Mozilla shows interest in implementing it sometime soon, then I'd personally support shipping only the promise based API and not the legacy callback-based API.  Otherwise I'm fine getting caught up to Mozilla first by shipping the existing API, and worrying about adding a promised based API as a follow-up step.

My main worry about this plan would be that it's creating future cleanup work for ourselves, as authors start using the now-in-two-browsers callback API. How long would it be until we're adding use counters and deprecation warnings to the callback version, and agonizing over how many long-tail websites might break if we remove it? It seems better to try to avoid these kind of cruft-accumulations in the first place, when we have a chance to see them coming.

I've CCed Kyle Huey who was the original implementer for <canvas>.toBlob(callback) on the Mozilla side. Kyle, if we managed to spec a promise-based version within the next day or two, would Mozilla be interested in implementing soon?

Boris Zbarsky

unread,
Dec 3, 2015, 11:31:06 AM12/3/15
to blink-dev
On 12/3/15 10:11 AM, Domenic Denicola wrote:
> Maybe with a different name, if we are worried about Gecko
> compatibility

There is a common-ish situation in which toBlob is supposed to throw: if
the canvas is tainted. Converting it to return Promise would mean it
never throws, and suddenly code written to the current API would no
longer work correctly.

So the options there are to have a function that sometimes returns a
rejected promise and sometimes throws, depending on how it's called, or
to just use a different name for the Promise version.

-Boris

Justin Novosad

unread,
Dec 3, 2015, 11:39:07 AM12/3/15
to Boris Zbarsky, blink-dev
It can reject the promise with an SecurityError exception object. 


-Boris



Boris Zbarsky

unread,
Dec 3, 2015, 12:07:25 PM12/3/15
to Justin Novosad, blink-dev
It can, but existing code using the API would break in that situation,
no? It would not get an exception (which is what it gets now) and it
would not get its callback called either.

-Boris

Justin Novosad

unread,
Dec 3, 2015, 12:31:35 PM12/3/15
to Boris Zbarsky, blink-dev
I think that when existing code switches to the promise version, it can do something like:

canvas.toBlob().then(successCallback, function(error) { throw error; });



-Boris


Boris Zbarsky

unread,
Dec 3, 2015, 12:40:13 PM12/3/15
to Justin Novosad, blink-dev
On 12/3/15 12:31 PM, Justin Novosad wrote:
> I think that when existing code switches to the promise version

That will happen as soon as an overload with the same name that returns
Promise is added, unless we somehow make it possible to have two
overloads one of which returns a Promise and one of which does not.
Which was in fact one of the options I listed in my mail, but is
generally considered bad API and isn't really supported by WebIDL at the
moment.

We're now going in circles.

-Boris

Domenic Denicola

unread,
Dec 3, 2015, 1:09:47 PM12/3/15
to Boris Zbarsky, Justin Novosad, blink-dev
From: blin...@chromium.org [mailto:blin...@chromium.org] On Behalf Of Boris Zbarsky


> We're now going in circles.

I agree there are definitely transitional problems if we were to reuse or overload the toBlob() name. As such I suggest a promise-returning convertToBlob(), alongside---ideally---removing toBlob().

We can discuss this aspect of things more in https://github.com/whatwg/html/issues/379.

Rick Byers

unread,
Dec 8, 2015, 2:28:56 PM12/8/15
to Domenic Denicola, Boris Zbarsky, Justin Novosad, blink-dev
The API owners met today and discussed this issue.

Overall we don't think the desire for a Promise-based API (which we all agree is better) should block shipping the existing callback-based API.  In particular, the role of the API owners is to ensure our policy and process has been correctly followed, not to police the details of every API.  We'd LOVE to see some consensus reached in the HTML spec community to add a promise-based API, and if this happened quickly (with support from at least one other vendor) we would be happy to see only the promise-based API ship.  But this isn't sufficient justification for us to block shipping a useful and reasonable API that has been long-spec'd and implemented by another browser.

We have over a month until M49 branches.  One option for Olivia would be to ship toBlob as it is now, and if it ends up getting replaced in the spec before branch point, update the implementation to match the new spec.

Rick

Jochen Eisinger

unread,
Dec 8, 2015, 3:31:59 PM12/8/15
to Rick Byers, Domenic Denicola, Boris Zbarsky, Justin Novosad, blink-dev

As discussed in the meeting, lgtm3 to ship
Reply all
Reply to author
Forward
0 new messages