Re: [FileAPI] Deterministic release of Blob proposal
On Thu, 08 Mar 2012 00:58:02 +0100, Feras Moussa fer...@microsoft.com wrote: In the case where close was called on a Blob that is being used in a pending request, then the request should be canceled. The expected result is the same as if abort() was called. It seems very weird that invoking close() on Blob would invoke abort() on XMLHttpRequest. Would it not be better to not set the close flag until it is no longer in use? -- Anne van Kesteren http://annevankesteren.nl/
Re: [FileAPI] Deterministic release of Blob proposal
On Wed, Mar 7, 2012 at 5:58 PM, Feras Moussa fer...@microsoft.com wrote: In the case where close was called on a Blob that is being used in a pending request, then the request should be canceled. The expected result is the same as if abort() was called. This would complicate every API that uses Blobs. APIs should just make a copy of the underlying data. It minimizes the effects on other APIs and makes the behavior consistently understandable. In the case of XHR2, the only change you'd need to make to that API, I think, would be for send() to say if *data* is a *neutered* object, throw an exception in step 3 of send(). The rest is already dealt with, since XHR2 already makes a copy (Let the request entity body be the raw data represented by data.). It simply means that any time you pass a Blob to a native API, the Blob is implicitly sliced to create an independent (shallow, of course) copy before it's used or stashed for later use. That way, APIs never have to deal with blobs being released out from underneath them, which could complicate things significantly (eg. you might be accessing the blob's data from an asynchronous section). var a = new Image(); a.onerror = function() { console.log(Oh no, my parent was neutered!); }; a.src = URL.createObjectURL(blob); blob.close(); Is that error going to hit? I documented this in my proposal, but in this case the URI would have been minted prior to calling close. The Blob URI would still resolve until it has been revoked, so in your example onerror would not be hit due to calling close. I do think this is what should happen, because createObjectURL would create a copy of blob. It seems a bit inconsistent with what your proposal, though (if blob.close() always releases the underlying data, to the point of aborting asynchronous XHR, then it should do so if it has associated URLs, too). -- Glenn Maynard
Re: [FileAPI] Deterministic release of Blob proposal
On Wed, 07 Mar 2012 02:12:39 +0100, Feras Moussa fer...@microsoft.com wrote: xhr.send(blob); blob.close(); // method name TBD In our implementation, this case would fail. We think this is reasonable because the need for having a close() method is to allow deterministic release of the resource. Reasonable or not, would fail is not something we can put in a standard. What happens exactly? What if a connection is established and data is being transmitted already? -- Anne van Kesteren http://annevankesteren.nl/
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 6:29 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Mar 6, 2012 at 4:24 PM, Michael Nordman micha...@google.com wrote: You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter. There is an existing mechanism for closing objects. It's called neutering. Blob.close should use the same terminology, whether or not the object is a Transferable. On Tue, Mar 6, 2012 at 4:25 PM, Kenneth Russell k...@google.com wrote: I would be hesitant to impose a close() method on all future Transferable types. Why? All Transferable types must define how to neuter objects; all close() does is trigger it. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. That's often not possible, when the ArrayBuffer is returned to you from an API (eg. XHR2). This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. No new semantics need to be defined; the semantics of Transferable are defined by postMessage and are the same for all transferable objects. That's already done. The only thing that needs to be defined is how to neuter an object, which is what Blob.close() has to define anyway. Using Transferable for Blob will allow Blobs, ArrayBuffers, and any future large, structured clonable objects to all be released with the same mechanisms: either pass them in the transfer argument to a postMessage call, or use the consistent, identical close() method inherited from Transferable. This allows developers to think of the transfer list as a list of objects which won't be needed after the postMessage call. It doesn't matter that the underlying optimizations are different; the visible side-effects are identical (the object can no longer be accessed). Closing an object, and neutering it because it was transferred to a different owner, are different concepts. It's already been demonstrated that Blobs, being read-only, do not need to be transferred in order to send them efficiently from one owner to another. It's also been demonstrated that Blobs can be resource intensive and that an explicit closing mechanism is needed. I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. -Ken
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Wed, Mar 7, 2012 at 11:38 AM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 6:29 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Mar 6, 2012 at 4:24 PM, Michael Nordman micha...@google.com wrote: You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter. There is an existing mechanism for closing objects. It's called neutering. Blob.close should use the same terminology, whether or not the object is a Transferable. On Tue, Mar 6, 2012 at 4:25 PM, Kenneth Russell k...@google.com wrote: I would be hesitant to impose a close() method on all future Transferable types. Why? All Transferable types must define how to neuter objects; all close() does is trigger it. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. That's often not possible, when the ArrayBuffer is returned to you from an API (eg. XHR2). This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. No new semantics need to be defined; the semantics of Transferable are defined by postMessage and are the same for all transferable objects. That's already done. The only thing that needs to be defined is how to neuter an object, which is what Blob.close() has to define anyway. Using Transferable for Blob will allow Blobs, ArrayBuffers, and any future large, structured clonable objects to all be released with the same mechanisms: either pass them in the transfer argument to a postMessage call, or use the consistent, identical close() method inherited from Transferable. This allows developers to think of the transfer list as a list of objects which won't be needed after the postMessage call. It doesn't matter that the underlying optimizations are different; the visible side-effects are identical (the object can no longer be accessed). Closing an object, and neutering it because it was transferred to a different owner, are different concepts. It's already been demonstrated that Blobs, being read-only, do not need to be transferred in order to send them efficiently from one owner to another. It's also been demonstrated that Blobs can be resource intensive and that an explicit closing mechanism is needed. I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. This makes sense to me. Blob needs close independent of whether it's in Transferable, and Blob has no need to be Transferable, so let's not mix the two.
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Mar 7, 2012, at 11:38 AM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 6:29 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Mar 6, 2012 at 4:24 PM, Michael Nordman micha...@google.com wrote: You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter. There is an existing mechanism for closing objects. It's called neutering. Blob.close should use the same terminology, whether or not the object is a Transferable. On Tue, Mar 6, 2012 at 4:25 PM, Kenneth Russell k...@google.com wrote: I would be hesitant to impose a close() method on all future Transferable types. Why? All Transferable types must define how to neuter objects; all close() does is trigger it. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. That's often not possible, when the ArrayBuffer is returned to you from an API (eg. XHR2). This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. No new semantics need to be defined; the semantics of Transferable are defined by postMessage and are the same for all transferable objects. That's already done. The only thing that needs to be defined is how to neuter an object, which is what Blob.close() has to define anyway. Using Transferable for Blob will allow Blobs, ArrayBuffers, and any future large, structured clonable objects to all be released with the same mechanisms: either pass them in the transfer argument to a postMessage call, or use the consistent, identical close() method inherited from Transferable. This allows developers to think of the transfer list as a list of objects which won't be needed after the postMessage call. It doesn't matter that the underlying optimizations are different; the visible side-effects are identical (the object can no longer be accessed). Closing an object, and neutering it because it was transferred to a different owner, are different concepts. It's already been demonstrated that Blobs, being read-only, do not need to be transferred in order to send them efficiently from one owner to another. It's also been demonstrated that Blobs can be resource intensive and that an explicit closing mechanism is needed. I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. I think there's broad enough consensus amongst vendors to table the discussion about adding close to Transferable. Would you please let me know why ypu believe ArrayBuffer should not have a close method? I would like some clarity here. The Typed Array spec would not be cluttered by the addition of a simple close method. I work much more with ArrayBuffer than Blob. I suspect others will too as they progress with more advanced and resource intensive applications. What is the use-case distinction between close of immutable blob and close of a mutable buffer? -Charles
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 1:18 PM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 12:04 PM, Greg Billock gbill...@google.com wrote: On Mon, Mar 5, 2012 at 6:46 PM, Charles Pritchard ch...@jumis.com wrote: On 3/5/2012 5:56 PM, Glenn Maynard wrote: On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. Web Intents won't have a transfer map argument. http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#widl-Intent-data For the Web Intents structured cloning algorithm, Web Intents would be inserting into step 3: If input is a Transferable object, add it to the transfer map. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm Then Web Intents would move the first section of the structured cloning algorithm to follow the internal cloning algorithm section, swapping their order. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data That's my understanding. We've been discussing the merits of this approach vs using a transfer array argument. There's a lot to like about this alternative -- it conserves arguments and looks simpler than the transfer map, as well as not having the headaches of whether you can do (null, [port]) or (port, [port]) and concerns like that. The advantage of using the transfer map param is that it is more contiguous with existing practice. We'd kind of hoped that this particular debate was finalized before we got to the point of needing to make a decision, so we bluffed and left it out of the web intents spec draft. :-) At this point, I'm leaning toward needing to add a transfer map parameter, and then dealing with that alongside other uses, given the state of thinking on Transferables support and the need to make this pretty consistent across structure clone invocations. I do think that complexity might be better solved by the type system (i.e. a new Transferable(ArrayBuffer)), which would require a different developer mechanic to set up clone vs transfer, but would relieve complexity in the invocation of structured clone itself: transferables could just always transfer transparently. I don't know if, given current practice with MessagePort, that kind of solution is available. A change like this would be feasible as long as it doesn't break compatibility. In other words, the current Transferable array would still need to be supported, but Transferable instances (or perhaps instances of some other type) wrapping another Transferable object would also express the intent. The current API for Transferable and postMessage was informed by the realization that the previous sequenceMessagePort argument to postMessage was essentially already expressing the Transferable concept. I'm not familiar with the Web Intents API, but at first glance it seems feasible to overload the constructor, postResult and postFailure methods to support passing a sequenceTransferable as the last argument. This would make the API look more like postMessage and avoid adding more transfer semantics. Is that possible? Yes. That's our current plan. -Greg
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Wed, Mar 7, 2012 at 12:02 PM, Charles Pritchard ch...@jumis.com wrote: On Mar 7, 2012, at 11:38 AM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 6:29 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Mar 6, 2012 at 4:24 PM, Michael Nordman micha...@google.com wrote: You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter. There is an existing mechanism for closing objects. It's called neutering. Blob.close should use the same terminology, whether or not the object is a Transferable. On Tue, Mar 6, 2012 at 4:25 PM, Kenneth Russell k...@google.com wrote: I would be hesitant to impose a close() method on all future Transferable types. Why? All Transferable types must define how to neuter objects; all close() does is trigger it. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. That's often not possible, when the ArrayBuffer is returned to you from an API (eg. XHR2). This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. No new semantics need to be defined; the semantics of Transferable are defined by postMessage and are the same for all transferable objects. That's already done. The only thing that needs to be defined is how to neuter an object, which is what Blob.close() has to define anyway. Using Transferable for Blob will allow Blobs, ArrayBuffers, and any future large, structured clonable objects to all be released with the same mechanisms: either pass them in the transfer argument to a postMessage call, or use the consistent, identical close() method inherited from Transferable. This allows developers to think of the transfer list as a list of objects which won't be needed after the postMessage call. It doesn't matter that the underlying optimizations are different; the visible side-effects are identical (the object can no longer be accessed). Closing an object, and neutering it because it was transferred to a different owner, are different concepts. It's already been demonstrated that Blobs, being read-only, do not need to be transferred in order to send them efficiently from one owner to another. It's also been demonstrated that Blobs can be resource intensive and that an explicit closing mechanism is needed. I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. I think there's broad enough consensus amongst vendors to table the discussion about adding close to Transferable. Would you please let me know why ypu believe ArrayBuffer should not have a close method? I would like some clarity here. The Typed Array spec would not be cluttered by the addition of a simple close method. It's certainly a matter of opinion -- but while it's only the addition of one method, it changes typed arrays' semantics to be much closer to manual memory allocation than they currently are. It would be a further divergence in behavior from ordinary ECMAScript arrays. The TC39 working group, I have heard, is incorporating typed arrays into the language specification, and for this reason I believe extreme care is warranted when adding more functionality to the typed array spec. The spec can certainly move forward, but personally I'd like to check with TC39 on semantic changes like this one. That's the rationale behind my statement above about preferring not to add this method at this time. -Ken I work much more with ArrayBuffer than Blob. I suspect others will too as they progress with more advanced and resource intensive applications. What is the use-case distinction between close of immutable blob and close of a mutable buffer? -Charles
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On 3/7/12 12:34 PM, Kenneth Russell wrote: On Wed, Mar 7, 2012 at 12:02 PM, Charles Pritchardch...@jumis.com wrote: On Mar 7, 2012, at 11:38 AM, Kenneth Russellk...@google.com wrote: I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. I think there's broad enough consensus amongst vendors to table the discussion about adding close to Transferable. Would you please let me know why ypu believe ArrayBuffer should not have a close method? I would like some clarity here. The Typed Array spec would not be cluttered by the addition of a simple close method. It's certainly a matter of opinion -- but while it's only the addition of one method, it changes typed arrays' semantics to be much closer to manual memory allocation than they currently are. It would be a further divergence in behavior from ordinary ECMAScript arrays. The TC39 working group, I have heard, is incorporating typed arrays into the language specification, and for this reason I believe extreme care is warranted when adding more functionality to the typed array spec. The spec can certainly move forward, but personally I'd like to check with TC39 on semantic changes like this one. That's the rationale behind my statement above about preferring not to add this method at this time. Searching through the net tells me that this has been a rumor for years. I agree with taking extreme care -- so let's isolate one more bit of information: Is ArrayBuffer being proposed for TC39 incorporation, or is it only the Typed Arrays? The idea here is to alter ArrayBuffer, an object which can be neutered via transfer map. It seems a waste to have to create a Worker to close down buffer views. Will TC39 have anything to say about the neuter concept and/or Web Messaging? Again, I'm bringing this up for the same practical experience that Blob.close() was brought up. I do appreciate that read/write allocation is a separate semantic from write-once/read-many allocation. I certainly don't want to derail the introduction of Typed Array into TC39. I don't want to sit back for two years either, while the ArrayBuffer object is in limbo. If necessary, I'll do some of the nasty test work of creating a worker simply to destroy buffers, and report back on it. var worker = new Worker('trash.js'); worker.postMessage(null,[bufferToClose]); worker.close(); vs. bufferToClose.close(); -Charles
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Wed, Mar 7, 2012 at 1:00 PM, Charles Pritchard ch...@jumis.com wrote: On 3/7/12 12:34 PM, Kenneth Russell wrote: On Wed, Mar 7, 2012 at 12:02 PM, Charles Pritchardch...@jumis.com wrote: On Mar 7, 2012, at 11:38 AM, Kenneth Russellk...@google.com wrote: I believe that we should fix the immediate problem and add a close() method to Blob. I'm not in favor of adding a similar method to ArrayBuffer at this time and therefore not to Transferable. There is a high-level goal to keep the typed array specification as minimal as possible, and having Transferable support leak in to the public methods of the interfaces contradicts that goal. I think there's broad enough consensus amongst vendors to table the discussion about adding close to Transferable. Would you please let me know why ypu believe ArrayBuffer should not have a close method? I would like some clarity here. The Typed Array spec would not be cluttered by the addition of a simple close method. It's certainly a matter of opinion -- but while it's only the addition of one method, it changes typed arrays' semantics to be much closer to manual memory allocation than they currently are. It would be a further divergence in behavior from ordinary ECMAScript arrays. The TC39 working group, I have heard, is incorporating typed arrays into the language specification, and for this reason I believe extreme care is warranted when adding more functionality to the typed array spec. The spec can certainly move forward, but personally I'd like to check with TC39 on semantic changes like this one. That's the rationale behind my statement above about preferring not to add this method at this time. Searching through the net tells me that this has been a rumor for years. Regardless of rumors I have talked to multiple members of TC39 who have clearly stated it is being incorporated into ES6 Harmony. I agree with taking extreme care -- so let's isolate one more bit of information: Is ArrayBuffer being proposed for TC39 incorporation, or is it only the Typed Arrays? The idea here is to alter ArrayBuffer, an object which can be neutered via transfer map. It seems a waste to have to create a Worker to close down buffer views. Both ArrayBuffer and the typed array views will be incorporated. Will TC39 have anything to say about the neuter concept and/or Web Messaging? This is an excellent question and one which I've also posed to TC39. I don't see how the language spec could reference these concepts. I'm guessing that this is an area that TC39 hasn't yet figured out, either. Again, I'm bringing this up for the same practical experience that Blob.close() was brought up. I do appreciate that read/write allocation is a separate semantic from write-once/read-many allocation. I certainly don't want to derail the introduction of Typed Array into TC39. I don't want to sit back for two years either, while the ArrayBuffer object is in limbo. Understood and appreciated. If necessary, I'll do some of the nasty test work of creating a worker simply to destroy buffers, and report back on it. var worker = new Worker('trash.js'); worker.postMessage(null,[bufferToClose]); worker.close(); vs. bufferToClose.close(); I doubt that that will work. Garbage collection will still need to run in the worker's JavaScript context in order for the transferred ArrayBuffer to be cleaned up, and I doubt that happens eagerly upon shutdown of the worker. Would be happy to be proven wrong. If you prototype adding ArrayBuffer.close() in your open source browser of choice and report back on significant efficiency improvements in a real-world use case, that would be valuable feedback. -Ken
Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 5:12 PM, Feras Moussa fer...@microsoft.com wrote: From: Arun Ranganathan [mailto:aranganat...@mozilla.com] Sent: Tuesday, March 06, 2012 1:27 PM To: Feras Moussa Cc: Adrian Bateman; public-webapps@w3.org; Ian Hickson; Anne van Kesteren Subject: Re: [FileAPI] Deterministic release of Blob proposal Feras, In practice, I think this is important enough and manageable enough to include in the spec., and I'm willing to slow the train down if necessary, but I'd like to understand a few things first. Below: At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. Do you agree that Transferable (http://dev.w3.org/html5/spec/Overview.html#transferable-objects) seems to be what we're looking for, and that Blob should implement Transferable? Transferable addresses the use case of copying across threads, and neuters the source object (though honestly, the word neuter makes me wince -- naming is a problem on the web). We can have a more generic method on Transferable that serves our purpose here, rather than *.close(), and Blob can avail of that. This is something we can work out with HTML, and might be the right thing to do for the platform (although this creates something to think about for MessagePort and for ArrayBuffer, which also implement Transferable). I agree with your changes, but am confused by some edge cases: To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. So Blob.slice() already presumes a new Blob, but I can certainly make this clearer. And I agree with the changes above, including the addition
RE: [FileAPI] Deterministic release of Blob proposal
Then let's try this again. var a = new Image(); a.onerror = function() { console.log(Oh no, my parent was neutered!); }; a.src = URL.createObjectURL(blob); blob.close(); Is that error going to hit? I documented this in my proposal, but in this case the URI would have been minted prior to calling close. The Blob URI would still resolve until it has been revoked, so in your example onerror would not be hit due to calling close. var a = new Worker('#'); a.postMessage(blob); blob.close(); Is that blob going to make it to the worker? SCA runs synchronously (so that subsequent changes to mutable values in the object don't impact the message) so the blob will have been cloned prior to close. The above would work as expected.
RE: [FileAPI] Deterministic release of Blob proposal
-Original Message- From: Anne van Kesteren [mailto:ann...@opera.com] Sent: Wednesday, March 07, 2012 12:49 AM To: Arun Ranganathan; Feras Moussa Cc: Adrian Bateman; public-webapps@w3.org; Ian Hickson Subject: Re: [FileAPI] Deterministic release of Blob proposal On Wed, 07 Mar 2012 02:12:39 +0100, Feras Moussa fer...@microsoft.com wrote: xhr.send(blob); blob.close(); // method name TBD In our implementation, this case would fail. We think this is reasonable because the need for having a close() method is to allow deterministic release of the resource. Reasonable or not, would fail is not something we can put in a standard. What happens exactly? What if a connection is established and data is being transmitted already? In the case where close was called on a Blob that is being used in a pending request, then the request should be canceled. The expected result is the same as if abort() was called.
Re: [FileAPI] Deterministic release of Blob proposal
On 3/7/12 3:56 PM, Feras Moussa wrote: Then let's try this again. var a = new Image(); a.onerror = function() { console.log(Oh no, my parent was neutered!); }; a.src = URL.createObjectURL(blob); blob.close(); Is that error going to hit? until it has been revoked, so in your example onerror would not be hit due to calling close. var a = new Worker('#'); a.postMessage(blob); blob.close(); The above would work as expected. Well that all makes sense; so speaking for myself, I'm still confused about this one thing: xhr.send(blob); blob.close(); // method name TBD In our implementation, this case would fail. We think this is reasonable because the So you want this to be a situation where we monitor progress events of XHR before releasing the blob? It seems feasible to monitor the upload progress, but it is a little awkward. -Charles
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Mon, Mar 5, 2012 at 6:46 PM, Charles Pritchard ch...@jumis.com wrote: On 3/5/2012 5:56 PM, Glenn Maynard wrote: On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. Web Intents won't have a transfer map argument. http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#widl-Intent-data For the Web Intents structured cloning algorithm, Web Intents would be inserting into step 3: If input is a Transferable object, add it to the transfer map. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm Then Web Intents would move the first section of the structured cloning algorithm to follow the internal cloning algorithm section, swapping their order. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data That's my understanding. We've been discussing the merits of this approach vs using a transfer array argument. There's a lot to like about this alternative -- it conserves arguments and looks simpler than the transfer map, as well as not having the headaches of whether you can do (null, [port]) or (port, [port]) and concerns like that. The advantage of using the transfer map param is that it is more contiguous with existing practice. We'd kind of hoped that this particular debate was finalized before we got to the point of needing to make a decision, so we bluffed and left it out of the web intents spec draft. :-) At this point, I'm leaning toward needing to add a transfer map parameter, and then dealing with that alongside other uses, given the state of thinking on Transferables support and the need to make this pretty consistent across structure clone invocations. I do think that complexity might be better solved by the type system (i.e. a new Transferable(ArrayBuffer)), which would require a different developer mechanic to set up clone vs transfer, but would relieve complexity in the invocation of structured clone itself: transferables could just always transfer transparently. I don't know if, given current practice with MessagePort, that kind of solution is available. Something like this may be necessary if Blob were a Transferable: var keepBlob = blob.slice(); var intent = new Intent(-x-my-intent, blob); navigator.startActivity(intent, callback); And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. Example of how easy the neutered concept applies to Transferrable: var blob = new Blob(my big blob); blob.close(); I like the idea of having Blob implement Transferrable and adding close to the Transferrable interface. File.close could have a better relationship with the cache and/or locks on data. Some history on Transferrable and structured clones: Note: MessagePort does have a close method and is currently the only Transferrable mentioned in WHATWG: http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#transferable-objects ArrayBuffer is widely implemented. It was the second item to implement Transferrable: http://www.khronos.org/registry/typedarray/specs/latest/#9 Subsequently, ImageData adopted Uint8ClampedArray for one of its properties, adopting TypedArrays: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata This has lead to some instability in the structured clone algorithm for ImageData as the typed array object for ImageData is read-only. https://www.w3.org/Bugs/Public/show_bug.cgi?id=13800 ArrayBuffer is still in a strawman state. -Charles
Re: [FileAPI] Deterministic release of Blob proposal
After a brief internal discussion, we like the idea over in Chrome-land. Let's make sure that we carefully spec out the edge cases, though. See below for some. On Fri, Mar 2, 2012 at 4:54 PM, Feras Moussa fer...@microsoft.com wrote: At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. What about: XHR.send(blob); blob.close(); or iframe.src = createObjectURL(blob); blob.close(); In the second example, if we say that the iframe does copy the blob, does that mean that closing the blob doesn't automatically revoke the URL, since it points at the new copy? Or does it point at the old copy and fail? Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. We’ve recently implemented this in experimental builds and have seen measurable performance improvements. The feedback we heard from our discussions with others at TPAC regarding our proposal to add a close() method to the Blob interface was that objects in the web platform potentially backed by expensive resources should have a deterministic way to be released. Thanks, Feras [1] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1499.html
Re: [FileAPI] Deterministic release of Blob proposal
It seems like this may be setting up a pattern for other dom objects which are large (like video/audio). When applied in this context, is close still a good verb for them? video.close(); dave PS I'm trying to not bikeshed too badly by avoiding a new name suggestion and allowing for the fact that close may be an ok name. On Tue, Mar 6, 2012 at 12:29 PM, Eric U er...@google.com wrote: After a brief internal discussion, we like the idea over in Chrome-land. Let's make sure that we carefully spec out the edge cases, though. See below for some. On Fri, Mar 2, 2012 at 4:54 PM, Feras Moussa fer...@microsoft.com wrote: At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. What about: XHR.send(blob); blob.close(); or iframe.src = createObjectURL(blob); blob.close(); In the second example, if we say that the iframe does copy the blob, does that mean that closing the blob doesn't automatically revoke the URL, since it points at the new copy? Or does it point at the old copy and fail? Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. We’ve recently implemented this in experimental builds and have seen measurable performance improvements. The feedback we heard from our discussions with others at TPAC regarding our proposal to add a close() method to the Blob interface was that objects in the web platform potentially backed by expensive resources should have a deterministic
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 12:04 PM, Greg Billock gbill...@google.com wrote: On Mon, Mar 5, 2012 at 6:46 PM, Charles Pritchard ch...@jumis.com wrote: On 3/5/2012 5:56 PM, Glenn Maynard wrote: On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. Web Intents won't have a transfer map argument. http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#widl-Intent-data For the Web Intents structured cloning algorithm, Web Intents would be inserting into step 3: If input is a Transferable object, add it to the transfer map. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm Then Web Intents would move the first section of the structured cloning algorithm to follow the internal cloning algorithm section, swapping their order. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data That's my understanding. We've been discussing the merits of this approach vs using a transfer array argument. There's a lot to like about this alternative -- it conserves arguments and looks simpler than the transfer map, as well as not having the headaches of whether you can do (null, [port]) or (port, [port]) and concerns like that. The advantage of using the transfer map param is that it is more contiguous with existing practice. We'd kind of hoped that this particular debate was finalized before we got to the point of needing to make a decision, so we bluffed and left it out of the web intents spec draft. :-) At this point, I'm leaning toward needing to add a transfer map parameter, and then dealing with that alongside other uses, given the state of thinking on Transferables support and the need to make this pretty consistent across structure clone invocations. I do think that complexity might be better solved by the type system (i.e. a new Transferable(ArrayBuffer)), which would require a different developer mechanic to set up clone vs transfer, but would relieve complexity in the invocation of structured clone itself: transferables could just always transfer transparently. I don't know if, given current practice with MessagePort, that kind of solution is available. A change like this would be feasible as long as it doesn't break compatibility. In other words, the current Transferable array would still need to be supported, but Transferable instances (or perhaps instances of some other type) wrapping another Transferable object would also express the intent. The current API for Transferable and postMessage was informed by the realization that the previous sequenceMessagePort argument to postMessage was essentially already expressing the Transferable concept. I'm not familiar with the Web Intents API, but at first glance it seems feasible to overload the constructor, postResult and postFailure methods to support passing a sequenceTransferable as the last argument. This would make the API look more like postMessage and avoid adding more transfer semantics. Is that possible? Something like this may be necessary if Blob were a Transferable: var keepBlob = blob.slice(); var intent = new Intent(-x-my-intent, blob); navigator.startActivity(intent, callback); And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. Example of how easy the neutered concept applies to Transferrable: var blob = new Blob(my big blob); blob.close(); I like the idea of having Blob implement Transferrable and adding close to the Transferrable interface. File.close could have a better relationship with the cache and/or locks on data. I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? -Ken Some history on Transferrable and structured clones: Note: MessagePort does have a close method and is currently the only Transferrable mentioned in WHATWG: http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#transferable-objects ArrayBuffer is widely implemented. It was the second item to implement
Re: [FileAPI] Deterministic release of Blob proposal
Feras, In practice, I think this is important enough and manageable enough to include in the spec., and I'm willing to slow the train down if necessary, but I'd like to understand a few things first. Below: - Original Message - At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new erro r , a ClosedError. This allows an application to signal when it's finished using the Blob. Do you agree that Transferable (http://dev.w3.org/html5/spec/Overview.html#transferable-objects) seems to be what we're looking for, and that Blob should implement Transferable? Transferable addresses the use case of copying across threads, and neuters the source object (though honestly, the word neuter makes me wince -- naming is a problem on the web). We can have a more generic method on Transferable that serves our purpose here, rather than *.close(), and Blob can avail of that. This is something we can work out with HTML, and might be the right thing to do for the platform (although this creates something to think about for MessagePort and for ArrayBuffer, which also implement Transferable). I agree with your changes, but am confused by some edge cases: To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. So Blob.slice() already presumes a new Blob, but I can certainly make this clearer. And I agree with the changes above, including the addition of something liked ClosedError (though I suppose this is an important enough error + exception to hash out with HTML and DOM4, and once again, the name is TBD). In your implementation, what happens exactly to Eric's edge cases, namely: xhr.send(blob); blob.close(); // method name TBD // AND frameRef.src = URL.createObjectURL(blob); blob.close() // method name TBD In my opinion, the
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
Ken, I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? Specifically, you think this is not something ArrayBuffer should inherit? If it's also a bad idea for MessagePort, then those are really our only two use cases of Transferable right now. I'm happy to create something like a close() on Blob. -- A*
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
Sounds like there's a good case for an explicit blob.close() method independent of 'transferable'. Separately defining blobs to be transferrable feels like an unneeded complexity. A caller wishing to neuter after sending can explicit call .close() rather than relying on more obscure artifacts of having also put the 'blob' in a 'transferrable' array. On Tue, Mar 6, 2012 at 1:18 PM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 12:04 PM, Greg Billock gbill...@google.com wrote: On Mon, Mar 5, 2012 at 6:46 PM, Charles Pritchard ch...@jumis.com wrote: On 3/5/2012 5:56 PM, Glenn Maynard wrote: On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. Web Intents won't have a transfer map argument. http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#widl-Intent-data For the Web Intents structured cloning algorithm, Web Intents would be inserting into step 3: If input is a Transferable object, add it to the transfer map. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm Then Web Intents would move the first section of the structured cloning algorithm to follow the internal cloning algorithm section, swapping their order. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data That's my understanding. We've been discussing the merits of this approach vs using a transfer array argument. There's a lot to like about this alternative -- it conserves arguments and looks simpler than the transfer map, as well as not having the headaches of whether you can do (null, [port]) or (port, [port]) and concerns like that. The advantage of using the transfer map param is that it is more contiguous with existing practice. We'd kind of hoped that this particular debate was finalized before we got to the point of needing to make a decision, so we bluffed and left it out of the web intents spec draft. :-) At this point, I'm leaning toward needing to add a transfer map parameter, and then dealing with that alongside other uses, given the state of thinking on Transferables support and the need to make this pretty consistent across structure clone invocations. I do think that complexity might be better solved by the type system (i.e. a new Transferable(ArrayBuffer)), which would require a different developer mechanic to set up clone vs transfer, but would relieve complexity in the invocation of structured clone itself: transferables could just always transfer transparently. I don't know if, given current practice with MessagePort, that kind of solution is available. A change like this would be feasible as long as it doesn't break compatibility. In other words, the current Transferable array would still need to be supported, but Transferable instances (or perhaps instances of some other type) wrapping another Transferable object would also express the intent. The current API for Transferable and postMessage was informed by the realization that the previous sequenceMessagePort argument to postMessage was essentially already expressing the Transferable concept. I'm not familiar with the Web Intents API, but at first glance it seems feasible to overload the constructor, postResult and postFailure methods to support passing a sequenceTransferable as the last argument. This would make the API look more like postMessage and avoid adding more transfer semantics. Is that possible? Something like this may be necessary if Blob were a Transferable: var keepBlob = blob.slice(); var intent = new Intent(-x-my-intent, blob); navigator.startActivity(intent, callback); And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. Example of how easy the neutered concept applies to Transferrable: var blob = new Blob(my big blob); blob.close(); I like the idea of having Blob implement Transferrable and adding close to the Transferrable interface. File.close could have a better relationship with the cache and/or locks on data. I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 3:18 PM, Kenneth Russell k...@google.com wrote: A change like this would be feasible as long as it doesn't break compatibility. In other words, the current Transferable array would still need to be supported, but Transferable instances (or perhaps instances of some other type) wrapping another Transferable object would also express the intent. I don't like this, because it loses the invariant that structured clone is a const operation by default. That is, if you don't explicitly specify objects in the transfer map, structured clone guarantees that the object you pass in won't be modified, and that (as a corollary) you can create as many structured clones as you want. This always works: function(obj) { thread1.postMessage(obj); thread2.postMessage(obj); thread3.postMessage(obj); } With the wrapper approach, it would no longer be guaranteed to work. I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? When would you explicitly want to disallow manually neutering a Transferable object? The only case I can think where it's not obviously useful is MessagePort, but I think that will be an exceptional case and that most Transferables will want this method. ArrayBuffer (currently the only other Transferable) will, of course. On Tue, Mar 6, 2012 at 3:34 PM, Michael Nordman micha...@google.com wrote: Separately defining blobs to be transferrable feels like an unneeded complexity. A caller wishing to neuter after sending can explicit call .close() rather than relying on more obscure artifacts of having also put the 'blob' in a 'transferrable' array. You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. -- Glenn Maynard
Re: [FileAPI] Deterministic release of Blob proposal
(I wish people wouldn't split threads.) On Tue, Mar 6, 2012 at 2:29 PM, Eric U er...@google.com wrote: What about: XHR.send(blob); blob.close(); This is the same as: XHR.send(arrayBuffer); postMessage({foo: arrayBuffer}, [arrayBuffer]); which you can already do. Both of these should always work, because send() synchronously makes a (logical) copy of the underlying data: If data is a ArrayBuffer Let the request entity body be the raw data represented by data. If data is a Blob Let the request entity body be the raw data represented by data. which happens before the call returns. or iframe.src = createObjectURL(blob); blob.close(); In the second example, if we say that the iframe does copy the blob, does that mean that closing the blob doesn't automatically revoke the URL, since it points at the new copy? Or does it point at the old copy and fail? Looking at this without involving iframe: You could define object URLs as references to a new copy of the blob. That would mean that if the blob is neutered while object URLs still point at it, a copy of the blob would have to be made by the UA even though it's transferred. Or, object URLs could be references to the blob itself. That means that if the blob is neutered, existing object URLs would be implicitly revoked. I'd suggest the former: when a Blob is passed to native APIs, make a (logical) copy of the Blob. More generally, I'd recommend that all native calls which accept a Blob, like createObjectURL, make a logical copy of the data, like XHR.send does. It's much easier to be consistent that way. On Tue, Mar 6, 2012 at 3:27 PM, Arun Ranganathan aranganat...@mozilla.com wrote: although this creates something to think about for MessagePort and for ArrayBuffer, which also implement Transferable). close() would be useful for ArrayBuffer, too. It's not obviously useful for MessagePort, but doesn't seem harmful for it to inherit it if it's not a big implementation burden. That's better than every single implementation of Transferable having to define this itself. -- Glenn Maynard
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
Separately defining blobs to be transferrable feels like an unneeded complexity. A caller wishing to neuter after sending can explicit call .close() rather than relying on more obscure artifacts of having also put the 'blob' in a 'transferrable' array. You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter.
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 1:31 PM, Arun Ranganathan aranganat...@mozilla.com wrote: Ken, I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? Specifically, you think this is not something ArrayBuffer should inherit? If it's also a bad idea for MessagePort, then those are really our only two use cases of Transferable right now. I'm happy to create something like a close() on Blob. MessagePort already defines a close() operation, so there's really no question of whether its presence is a good or bad idea there. A close() operation seems necessary in networking style APIs. I would be hesitant to impose a close() method on all future Transferable types. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. On Tue, Mar 6, 2012 at 1:34 PM, Michael Nordman micha...@google.com wrote: Sounds like there's a good case for an explicit blob.close() method independent of 'transferable'. Separately defining blobs to be transferrable feels like an unneeded complexity. A caller wishing to neuter after sending can explicit call .close() rather than relying on more obscure artifacts of having also put the 'blob' in a 'transferrable' array. This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. -Ken
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Mar 6, 2012, at 2:25 PM, Kenneth Russell k...@google.com wrote: On Tue, Mar 6, 2012 at 1:31 PM, Arun Ranganathan aranganat...@mozilla.com wrote: Ken, I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? Specifically, you think this is not something ArrayBuffer should inherit? If it's also a bad idea for MessagePort, then those are really our only two use cases of Transferable right now. I'm happy to create something like a close() on Blob. MessagePort already defines a close() operation, so there's really no question of whether its presence is a good or bad idea there. A close() operation seems necessary in networking style APIs. I would be hesitant to impose a close() method on all future Transferable types. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. By definition, Transferable objects can be neutered; we're talking about an explicit method for it. After that, it's up to implementers. I prefer .close to .release. An ArrayBuffer using 12megs of ram is something I want to release ASAP on mobile. .close would still allow for the optimization you're implying in memory mapping. On Tue, Mar 6, 2012 at 1:34 PM, Michael Nordman micha...@google.com wrote: Sounds like there's a good case for an explicit blob.close() method independent of 'transferable'. Separately defining blobs to be transferrable feels like an unneeded complexity. A caller wishing to neuter after sending can explicit call .close() rather than relying on more obscure artifacts of having also put the 'blob' in a 'transferrable' array. This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. Making Blob a Transferable may simplify the structured clone algorithm; Blob an File would no longer be explicitly listed. Adding close to Transferable would simplify three different objects -- ArrayBuffer, MessagePort and Blob. In theory anyway. While Blob doesn't need the transfer map optimization, it may be helpful in the context of web intents postMessage as it would release the Blob references from one window, possibly making GC a little easier. That's just a guess... But this thread is about enhancing the process. Seems reasonable that this would be a side effect. File.close() may have implementation side effects, such as releasing read locks on underlying files. -Charles
RE: [FileAPI] Deterministic release of Blob proposal
From: Arun Ranganathan [mailto:aranganat...@mozilla.com] Sent: Tuesday, March 06, 2012 1:27 PM To: Feras Moussa Cc: Adrian Bateman; public-webapps@w3.org; Ian Hickson; Anne van Kesteren Subject: Re: [FileAPI] Deterministic release of Blob proposal Feras, In practice, I think this is important enough and manageable enough to include in the spec., and I'm willing to slow the train down if necessary, but I'd like to understand a few things first. Below: At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. Do you agree that Transferable (http://dev.w3.org/html5/spec/Overview.html#transferable-objects) seems to be what we're looking for, and that Blob should implement Transferable? Transferable addresses the use case of copying across threads, and neuters the source object (though honestly, the word neuter makes me wince -- naming is a problem on the web). We can have a more generic method on Transferable that serves our purpose here, rather than *.close(), and Blob can avail of that. This is something we can work out with HTML, and might be the right thing to do for the platform (although this creates something to think about for MessagePort and for ArrayBuffer, which also implement Transferable). I agree with your changes, but am confused by some edge cases: To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. So Blob.slice() already presumes a new Blob, but I can certainly make this clearer. And I agree with the changes above, including the addition of something liked
RE: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
-Original Message- From: Arun Ranganathan [mailto:aranganat...@mozilla.com] Sent: Tuesday, March 06, 2012 1:32 PM To: Kenneth Russell Cc: public-webapps@w3.org; Charles Pritchard; Glenn Maynard; Feras Moussa; Adrian Bateman; Greg Billock Subject: Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal Ken, I'm not sure that adding close() to Transferable is a good idea. Not all Transferable types may want to support that explicit operation. What about adding close() to Blob, and having the neutering operation on Blob be defined to call close() on it? Specifically, you think this is not something ArrayBuffer should inherit? If it's also a bad idea for MessagePort, then those are really our only two use cases of Transferable right now. I'm happy to create something like a close() on Blob. -- A* We agree Blobs do not need to be transferrable, and thus it makes sense to have close directly on Blob, independent of being transferable.
Re: [FileAPI] Deterministic release of Blob proposal
On 3/6/12 5:12 PM, Feras Moussa wrote: frameRef.src = URL.createObjectURL(blob); blob.close() // method name TBD In my opinion, the first (using xhr) should succeed. In the second, frameRef.src works, but subsequent attempts to mint a Blob URI for the same 'blob' resource fail. Does this hold true for you? We agree that subsequent attempts to mint a blob URI for a blob that has been closed should fail, and is what I tried to clarify in my comments in 'section 6'. As an aside, the above example shows navigation to a Blob URI - this is not something we Currently support or intend to support. Then let's try this again. var a = new Image(); a.onerror = function() { console.log(Oh no, my parent was neutered!); }; a.src = URL.createObjectURL(blob); blob.close(); Is that error going to hit? var a = new Worker('#'); a.postMessage(blob); blob.close(); Is that blob going to make it to the worker? -Charles
Re: Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On Tue, Mar 6, 2012 at 4:24 PM, Michael Nordman micha...@google.com wrote: You can always call close() yourself, but Blob.close() should use the neuter mechanism already there, not make up a new one. Blobs aren't transferable, there is no existing mechanism that applies to them. Adding a blob.close() method is independent of making blob's transferable, the former is not prerequisite on the latter. There is an existing mechanism for closing objects. It's called neutering. Blob.close should use the same terminology, whether or not the object is a Transferable. On Tue, Mar 6, 2012 at 4:25 PM, Kenneth Russell k...@google.com wrote: I would be hesitant to impose a close() method on all future Transferable types. Why? All Transferable types must define how to neuter objects; all close() does is trigger it. I don't think adding one to ArrayBuffer would be a bad idea but I think that ideally it wouldn't be necessary. On memory constrained devices, it would still be more efficient to re-use large ArrayBuffers rather than close them and allocate new ones. That's often not possible, when the ArrayBuffer is returned to you from an API (eg. XHR2). This sounds like a good idea. As you pointed out offline, a key difference between Blobs and ArrayBuffers is that Blobs are always immutable. It isn't necessary to define Transferable semantics for Blobs in order to post them efficiently, but it was essential for ArrayBuffers. No new semantics need to be defined; the semantics of Transferable are defined by postMessage and are the same for all transferable objects. That's already done. The only thing that needs to be defined is how to neuter an object, which is what Blob.close() has to define anyway. Using Transferable for Blob will allow Blobs, ArrayBuffers, and any future large, structured clonable objects to all be released with the same mechanisms: either pass them in the transfer argument to a postMessage call, or use the consistent, identical close() method inherited from Transferable. This allows developers to think of the transfer list as a list of objects which won't be needed after the postMessage call. It doesn't matter that the underlying optimizations are different; the visible side-effects are identical (the object can no longer be accessed). -- Glenn Maynard
Re: [FileAPI] Deterministic release of Blob proposal
Feras - this seems kinda' late, especially since the two-week pre-LC comment period for File API ended Feb 24. Is this a feature that can be postponed to v.next? On 3/2/12 7:54 PM, ext Feras Moussa wrote: At TPAC we discussed the ability to deterministically close blobs with a few others. As we’ve discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we’ve seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics – calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a “ClosedError” DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL – If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data – namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. Similarly to how FileReader must act directly on the Blob’s data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. We’ve recently implemented this in experimental builds and have seen measurable performance improvements. The feedback we heard from our discussions with others at TPAC regarding our proposal to add a close() method to the Blob interface was that objects in the web platform potentially backed by expensive resources should have a deterministic way to be released. Thanks, Feras [1] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1499.html
RE: [FileAPI] Deterministic release of Blob proposal
The feedback is implementation feedback that we have refined in the past few weeks as we've updated our implementation. We're happy with it to be treated as a LC comment, but we'd also give this feedback in CR too since in recent weeks we've found it to be a problem in apps which make extensive use of the APIs. -Original Message- From: Arthur Barstow [mailto:art.bars...@nokia.com] Sent: Monday, March 05, 2012 12:52 PM To: Feras Moussa; Arun Ranganathan; Jonas Sicking Cc: public-webapps@w3.org; Adrian Bateman Subject: Re: [FileAPI] Deterministic release of Blob proposal Feras - this seems kinda' late, especially since the two-week pre-LC comment period for File API ended Feb 24. Is this a feature that can be postponed to v.next? On 3/2/12 7:54 PM, ext Feras Moussa wrote: At TPAC we discussed the ability to deterministically close blobs with a few others. As we've discussed in the createObjectURL thread[1], a Blob may represent an expensive resource (eg. expensive in terms of memory, battery, or disk space). At present there is no way for an application to deterministically release the resource backing the Blob. Instead, an application must rely on the resource being cleaned up through a non-deterministic garbage collector once all references have been released. We have found that not having a way to deterministically release the resource causes a performance impact for a certain class of applications, and is especially important for mobile applications or devices with more limited resources. In particular, we've seen this become a problem for media intensive applications which interact with a large number of expensive blobs. For example, a gallery application may want to cycle through displaying many large images downloaded through websockets, and without a deterministic way to immediately release the reference to each image Blob, can easily begin to consume vast amounts of resources before the garbage collector is executed. To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. To support this change, the following changes in the File API spec are needed: * In section 6 (The Blob Interface) - Addition of a close method. When called, the close method releases the underlying resource of the Blob. Close renders the blob invalid, and further operations such as URL.createObjectURL or the FileReader read methods on the closed blob will fail and return a ClosedError. If there are any non-revoked URLs to the Blob, these URLs will continue to resolve until they have been revoked. - For the slice method, state that the returned Blob is a new Blob with its own lifetime semantics - calling close on the new Blob is independent of calling close on the original Blob. *In section 8 (The FIleReader Interface) - State the FileReader reads directly over the given Blob, and not a copy with an independent lifetime. * In section 10 (Errors and Exceptions) - Addition of a ClosedError. If the File or Blob has had the close method called, then for asynchronous read methods the error attribute MUST return a ClosedError DOMError and synchronous read methods MUST throw a ClosedError exception. * In section 11.8 (Creating and Revoking a Blob URI) - For createObjectURL - If this method is called with a closed Blob argument, then user agents must throw a ClosedError exception. Similarly to how slice() clones the initial Blob to return one with its own independent lifetime, the same notion will be needed in other APIs which conceptually clone the data - namely FormData, any place the Structured Clone Algorithm is used, and BlobBuilder. Similarly to how FileReader must act directly on the Blob's data, the same notion will be needed in other APIs which must act on the data - namely XHR.send and WebSocket. These APIs will need to throw an error if called on a Blob that was closed and the resources are released. We've recently implemented this in experimental builds and have seen measurable performance improvements. The feedback we heard from our discussions with others at TPAC regarding our proposal to add a close() method to the Blob interface was that objects in the web platform potentially backed by expensive resources should have a deterministic way to be released. Thanks, Feras [1] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1499.htm l
Re: [FileAPI] Deterministic release of Blob proposal
On Fri, Mar 2, 2012 at 6:54 PM, Feras Moussa fer...@microsoft.com wrote: To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. This is exactly like the neuter concept, defined at http://dev.w3.org/html5/spec/common-dom-interfaces.html#transferable-objects. I recommend using it. Make Blob a Transferable, and have close() neuter the object. The rest of this wouldn't change much, except you'd say if the object has been neutered (or has the neutered flag set, or however it's defined) instead of if the close method has been called. Originally, I think it was assumed that Blobs don't need to be Transferable, because they're immutable, which means you don't (necessarily) need to make a copy when transferring them between threads. That was only considering the cost of copying the Blob, though, not the costs of delayed GC that you're talking about here, so I think transferable Blobs do make sense. Also, the close() method should probably go on Transferable (with a name less likely to clash, eg. neuter), instead of as a one-off on Blob. If it's useful for Blob, it's probably useful for ArrayBuffer and all other future Transferables as well. -- Glenn Maynard
Re: [FileAPI] Deterministic release of Blob proposal
On 3/5/2012 3:59 PM, Glenn Maynard wrote: On Fri, Mar 2, 2012 at 6:54 PM, Feras Moussa fer...@microsoft.com mailto:fer...@microsoft.com wrote: To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. This is exactly like the neuter concept, defined at http://dev.w3.org/html5/spec/common-dom-interfaces.html#transferable-objects. I recommend using it. Make Blob a Transferable, and have close() neuter the object. The rest of this wouldn't change much, except you'd say if the object has been neutered (or has the neutered flag set, or however it's defined) instead of if the close method has been called. Originally, I think it was assumed that Blobs don't need to be Transferable, because they're immutable, which means you don't (necessarily) need to make a copy when transferring them between threads. That was only considering the cost of copying the Blob, though, not the costs of delayed GC that you're talking about here, so I think transferable Blobs do make sense. Also, the close() method should probably go on Transferable (with a name less likely to clash, eg. neuter), instead of as a one-off on Blob. If it's useful for Blob, it's probably useful for ArrayBuffer and all other future Transferables as well. Glenn, Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? blob = keepBlob; // keeping a copy of my blob still in thread. Sorry to cover too many angles: if Blob is Transferable, then it'll neuter; so if we do want a local copy, we'd use slice ahead of time to keep it. And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. The new behavior is pretty easy. var blob = new Blob(my big blob); blob.close(); // My blob has been neutered before it could procreate. -Charles
Re: [FileAPI] Deterministic release of Blob proposal
On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? blob = keepBlob; // keeping a copy of my blob still in thread. Sorry to cover too many angles: if Blob is Transferable, then it'll neuter; so if we do want a local copy, we'd use slice ahead of time to keep it. You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. It'll throw TypeError, which you'll need to handle if you need to support older browsers. The new behavior is pretty easy. var blob = new Blob(my big blob); blob.close(); // My blob has been neutered before it could procreate. Sorry, I'm not really sure what you're trying to say. This still works when using the neutered concept; it just uses an existing mechanism, and allows transfers. -- Glenn Maynard
Transferable and structured clones, was: Re: [FileAPI] Deterministic release of Blob proposal
On 3/5/2012 5:56 PM, Glenn Maynard wrote: On Mon, Mar 5, 2012 at 7:04 PM, Charles Pritchard ch...@jumis.com mailto:ch...@jumis.com wrote: Do you see old behavior working something like the following? var blob = new Blob(my new big blob); var keepBlob = blob.slice(); destination.postMessage(blob, '*', [blob]); // is try/catch needed here? You don't need to do that. If you don't want postMessage to transfer the blob, then simply don't include it in the transfer parameter, and it'll perform a normal structured clone. postMessage behaves this way in part for backwards-compatibility: so exactly in cases like this, we can make Blob implement Transferable without breaking existing code. See http://dev.w3.org/html5/postmsg/#posting-messages and similar postMessage APIs. Web Intents won't have a transfer map argument. http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html#widl-Intent-data For the Web Intents structured cloning algorithm, Web Intents would be inserting into step 3: If input is a Transferable object, add it to the transfer map. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm Then Web Intents would move the first section of the structured cloning algorithm to follow the internal cloning algorithm section, swapping their order. http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data That's my understanding. Something like this may be necessary if Blob were a Transferable: var keepBlob = blob.slice(); var intent = new Intent(-x-my-intent, blob); navigator.startActivity(intent, callback); And we might have an error on postMessage stashing it in the transfer array if it's not a Transferable on an older browser. Example of how easy the neutered concept applies to Transferrable: var blob = new Blob(my big blob); blob.close(); I like the idea of having Blob implement Transferrable and adding close to the Transferrable interface. File.close could have a better relationship with the cache and/or locks on data. Some history on Transferrable and structured clones: Note: MessagePort does have a close method and is currently the only Transferrable mentioned in WHATWG: http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#transferable-objects ArrayBuffer is widely implemented. It was the second item to implement Transferrable: http://www.khronos.org/registry/typedarray/specs/latest/#9 Subsequently, ImageData adopted Uint8ClampedArray for one of its properties, adopting TypedArrays: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata This has lead to some instability in the structured clone algorithm for ImageData as the typed array object for ImageData is read-only. https://www.w3.org/Bugs/Public/show_bug.cgi?id=13800 ArrayBuffer is still in a strawman state. -Charles
Re: [FileAPI] Deterministic release of Blob proposal
On 3/2/2012 4:54 PM, Feras Moussa wrote: At TPAC we discussed the ability to deterministically close blobs with a few others. ... To address this issue, we propose that a close method be added to the Blob interface. When called, the close method should release the underlying resource of the Blob, and future operations on the Blob will return a new error, a ClosedError. This allows an application to signal when it's finished using the Blob. I suppose the theory of Blob is that it can be written to disk. The other theory is that reference counting can somehow work magic. I'm not sure, but it came up before. I brought up a close mechanism for ArrayBuffer, which is (I believe) supposed to be in memory, always. http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-January/029741.html Also referenced: http://www.khronos.org/webgl/public-mailing-list/archives/1009/msg00229.html ArrayBuffer can now be closed out of the current thread via Transferable semantics. I don't know if it disappears into space with an empty postMessage target. I don't think that works for Blob, though. Yes, I'd like to see immediate mechanisms to cleanup Blob and ArrayBuffer. In practical use, it wasn't an issue on the desktop and the iPhone hadn't picked up the semantics yet. But gosh it's no fun trying to navigate memory management on mobile device. Thus my low memory event thread. -Charles