Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 4:27 PM, Ojan Vafai wrote: > On Thu, Jul 5, 2012 at 1:02 PM, Ryosuke Niwa wrote: > >> On Thu, Jul 5, 2012 at 12:45 PM, James Graham wrote: >> >>> On Thu, 5 Jul 2012, Ryosuke Niwa wrote: >>> On Thu, Jul 5, 2012 at 8:08 AM, James Graham ** wrote: > On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: >> After this change, authors can write: >> scope.undoManager.transact(new AutomaticDOMTransaction{**function >> () { >>scope.appendChild("foo"); >> }, 'append "foo"')); >> >> [...] >>> >> document.undoManager.transact(**new DOMTransaction({function >> () { >>// Draw a line on canvas >>}, function () { >>// Undraw a line >>}, function () { this.execute(); }, >>'Draw a line' >> })); >> > > I think this proposed API looks particularly verbose and ugly. I > thought we wanted to make new APIs more author > friendly and less like refugees from Java-land. > What makes you say so? If anything, you don't have to have labels like execute, undo, and redo. So it's less verbose. If you don't like the long name like AutomaticDOMTransaction, we can come up with a shorter name. >>> >>> I think having to call a particular constructor for an object that is >>> just passed straight into a DOM function is verbose, and difficult to >>> internalise (because you have to remember the constructor name and case and >>> so on). I think the design with three positional arguments is much harder >>> to read than the design with three explicitly "named arguments" implemented >>> as object properties. >> >> >> But the alternative is having to remember labels like execute, undo, & >> redo. >> > > In your version, you need to remember the order of the arguments, which > requires you looking it up each time. If we do decide to add the > DOMTransaction constructor back, we should keep passing it a dictionary as > it's argument. Or maybe take the label and a dictionary as arguments. > That's true of almost all other Web APIs when used in ECMAScript 5. I'm not sympathetic to the argument that you have to remember orders in which arguments appear because that's true of all functions in ES5, C++, and various other programming languages. If we were to solve this problem (I'm not even convinced that this is a problem), then TC39 is the right place to discuss this issue. I do not want to turn the undo manager API spec into a scientific experiment for new syntax sugar in ES5. On Thu, Jul 5, 2012 at 4:40 PM, Yuval Sadan wrote: > > > t = undoManager.transact("foobar", function() { ... }); >> > t.onredo = function() { /* custom redo */ }; >> > t.execute(); >> > >> > Whether onundo/onredo are assigned upon execute() is well defined, so >> basing behavior on that is clear enough for me. Plus, I wonder - what is a >> non-automatic transaction without an undo? A freak? >> >> Also, the interface you proposed behaves somewhat oddly when the undo >> manager from which the transaction was created is disconnected since >> execute() will fail in such a case. >> > What I find appealing in this example is that the transaction is an > operation which is indeed disconnected from the UndoManager. Perhaps I'm > missing something here, but what do we gain by having UndoManager being the > place of both creation and execution of the DOMTransaction object? If I may > take the notion further, it might as well originate elsewhere, and connect > to an UndoManager only on execute(), e.g. > > t = document.transaction("foo", function() { }); // or new > DOMTransaction(), actually > t.onundo = function() { }; > undoManager.execute(t); > > I realize as I'm writing that this is a hybrid suggestion between new > DOMTransaction() and the event handler version. It gives reason for > introduction of the DOMTransaction() standalone instantiation. Perhaps I'm > going to far. It just seems logical. > Right, I like the separation of concerns. Your proposal here is almost identical to mine. I just made it easier to specify undo & redo as an argument to transaction (in my case of new DOMTransaction) so that instead of t = new DOMTransaction("foo", function () { }); t.onundo = function() { }; I can do just do: t = new DOMTransaction("foo", function () { }, function () { }); undoManager.execute(t); It encapsulates the action as well as the reverse action. I find this to be > explicit and simple enough to write without confusion. Every idea is > specified once and in a clear place - (a) what to do, (b) how to undo and > (c) execute. More specific than this would be verbose imho. > I'm totally fine with the constructor of document.transact just take the initial execute callback and undo/redo optionally specified as ES5 properties. > Another approach will be to make the second argument optional and treat >> all
Re: [UndoManager] Re-introduce DOMTransaction interface?
> > > > t = undoManager.transact("foobar", function() { ... }); > > t.onredo = function() { /* custom redo */ }; > > t.execute(); > > > > Whether onundo/onredo are assigned upon execute() is well defined, so > basing behavior on that is clear enough for me. Plus, I wonder - what is a > non-automatic transaction without an undo? A freak? > > Also, the interface you proposed behaves somewhat oddly when the undo > manager from which the transaction was created is disconnected since > execute() will fail in such a case. > What I find appealing in this example is that the transaction is an operation which is indeed disconnected from the UndoManager. Perhaps I'm missing something here, but what do we gain by having UndoManager being the place of both creation and execution of the DOMTransaction object? If I may take the notion further, it might as well originate elsewhere, and connect to an UndoManager only on execute(), e.g. t = document.transaction("foo", function() { }); // or new DOMTransaction(), actually t.onundo = function() { }; undoManager.execute(t); I realize as I'm writing that this is a hybrid suggestion between new DOMTransaction() and the event handler version. It gives reason for introduction of the DOMTransaction() standalone instantiation. Perhaps I'm going to far. It just seems logical. It encapsulates the action as well as the reverse action. I find this to be explicit and simple enough to write without confusion. Every idea is specified once and in a clear place - (a) what to do, (b) how to undo and (c) execute. More specific than this would be verbose imho. > Another approach will be to make the second argument optional and treat > all transactions created without a callback function as manual transactions > since there's no need for manual transaction's execute to be a callback. > I fear that changing placement of the execute function in different circumstances will cause confusion and that it is indeed too implicit.
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 1:02 PM, Ryosuke Niwa wrote: > On Thu, Jul 5, 2012 at 12:45 PM, James Graham wrote: > >> On Thu, 5 Jul 2012, Ryosuke Niwa wrote: >> >>> On Thu, Jul 5, 2012 at 8:08 AM, James Graham ** >>> wrote: >>> On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: > After this change, authors can write: > scope.undoManager.transact(new AutomaticDOMTransaction{**function > () { >scope.appendChild("foo"); > }, 'append "foo"')); > > [...] >> >>> > document.undoManager.transact(**new DOMTransaction({function () > { >// Draw a line on canvas >}, function () { >// Undraw a line >}, function () { this.execute(); }, >'Draw a line' > })); > I think this proposed API looks particularly verbose and ugly. I thought we wanted to make new APIs more author friendly and less like refugees from Java-land. >>> >>> >>> What makes you say so? If anything, you don't have to have labels like >>> execute, undo, and redo. So it's less verbose. If you >>> don't like the long name like AutomaticDOMTransaction, we can come up >>> with a shorter name. >>> >> >> I think having to call a particular constructor for an object that is >> just passed straight into a DOM function is verbose, and difficult to >> internalise (because you have to remember the constructor name and case and >> so on). I think the design with three positional arguments is much harder >> to read than the design with three explicitly "named arguments" implemented >> as object properties. > > > But the alternative is having to remember labels like execute, undo, & > redo. > In your version, you need to remember the order of the arguments, which requires you looking it up each time. If we do decide to add the DOMTransaction constructor back, we should keep passing it a dictionary as it's argument. Or maybe take the label and a dictionary as arguments. > Passing in objects containing one or more non-callback properties is also >> an increaingly common pattern, and we are trying to replace legacy APIs >> that took lots of positional arguments with options-object based >> replacements (e.g. init*Event). From the point of view of a javascript >> author there is no difference between something like {foo:true} and >> {foo:function(){}}. Insisting that there should be a difference in DOM APIs >> because of low-level implementation concerns is doing a disservice to web >> authors by increasing the impedence mismatch between the DOM and javascript. > > > Having an explicit constructor has other advantages like making expando > work. And we don't have to worry about authors modifying execute, undo, & > redo after the fact because we can make them readonly (making them not > readonly has some odd implications like the timing at which properties are > changed matter). > > Also, DOM transaction object currently have two mutually exclusive > functions executeAutomatic and execute, which define whether the > transaction is automatic or not, and this has very weird consequences such > as specifying both executeAutomatic and execute will result in an automatic > transaction. Having an explicit constructor makes this interface much more > clear and clean. > > On Thu, Jul 5, 2012 at 11:07 AM, Olli Pettay >>> wrote: >>> We shouldn't change the UndoManager API because of implementation issues, but if event based API ends up being better. >>> I don't think it's reasonable to agree on an unimplementable design. In >>> theory, mutation events can be implemented correctly >>> but we couldn't, so we're moving on and getting rid of it. >>> >> >> The current deisgn is not "unimplementable", it's just slightly more work >> in WebKit than you would like. I don't think it's reasonable to reject good >> designs in favour of worse designs simply because the better design isn't a >> perfect fit for a single implementation >> > > I don't think the current interface-less object is a good design > regardless of whether it could be implemented in WebKit or not. > > - Ryosuke > >
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Jul 5, 2012 2:50 PM, "Yuval Sadan" wrote: >> >> >> > To sum up, as an author I vote for-- >> > var t = undoManager.transact("foo"); >> > t.onundo = function() { ... }; >> > OR t.setUndo(function() { }); >> >> How do you envision it should work with an automatic transaction? >> >> We need some mechanism to tell the UA "record DOM mutations while I'm calling this function". > > My preliminary thought is that transactions should be automatic unless otherwise stated. Following that rationale, perhaps > > var t; > // performs automatic transaction, no undo or redo needs specifying > t = undoManager.transact("foo", function() { ... }); > t.execute(); > > t = undoManager.transact("bar", function() { ... }); > t.onundo = function() { /* custom undo */ }; > t.execute(); > > t = undoManager.transact("foobar", function() { ... }); > t.onredo = function() { /* custom redo */ }; > t.execute(); > > Whether onundo/onredo are assigned upon execute() is well defined, so basing behavior on that is clear enough for me. Plus, I wonder - what is a non-automatic transaction without an undo? A freak? Yeah, a manual transaction without undo/redo is somewhat oxymoron in that such an operation can be done completely outside of DOM transactions. If the only point of calling transact was to add an entry to the undo transaction history, then one can do so with an automatic transaction with a trivial function() {}. I'll that this is very similar to my original proposal where I had transact decide whether a given transaction was automatic or not based on whether undo/redo methods are provided or not (back then,they were called unapply and reapply). However, Jonas and Ehsan didn't like this idea if I remember correctly. They wanted a more explicit interface. Also, the interface you proposed behaves somewhat oddly when the undo manager from which the transaction was created is disconnected since execute() will fail in such a case. > Some more ideas -- besides the other more verbose solutions (having executeAutomatic(), a special property e.g. isAutomatic), you might extend the vocabulary of UndoManager: either offer an additional argument for transact (e.g. transact("foo", function() { ... }, true) ), or better imho, have transact() specify a custom transaction and introduce record() (just to avoid autoTransact()) which will specify an automatic transaction, thus having: > > t = undoManager.transact("lala", function() { }); > t.execute(); // error, transact() with no undo() > > t = undoManager.record("baba", function() {}); > t.onundo = function() { }; // will be ignored/error thrown, since we're on record() > t.execute(); Another approach will be to make the second argument optional and treat all transactions created without a callback function as manual transactions since there's no need for manual transaction's execute to be a callback. - Ryosuke
Re: [UndoManager] Re-introduce DOMTransaction interface?
> > > > To sum up, as an author I vote for-- > > var t = undoManager.transact("foo"); > > t.onundo = function() { ... }; > > OR t.setUndo(function() { }); > > How do you envision it should work with an automatic transaction? > > We need some mechanism to tell the UA "record DOM mutations while I'm > calling this function". > My preliminary thought is that transactions should be automatic unless otherwise stated. Following that rationale, perhaps var t; // performs automatic transaction, no undo or redo needs specifying t = undoManager.transact("foo", function() { ... }); t.execute(); t = undoManager.transact("bar", function() { ... }); t.onundo = function() { /* custom undo */ }; t.execute(); t = undoManager.transact("foobar", function() { ... }); t.onredo = function() { /* custom redo */ }; t.execute(); Whether onundo/onredo are assigned upon execute() is well defined, so basing behavior on that is clear enough for me. Plus, I wonder - what is a non-automatic transaction without an undo? A freak? Some more ideas -- besides the other more verbose solutions (having executeAutomatic(), a special property e.g. isAutomatic), you might extend the vocabulary of UndoManager: either offer an additional argument for transact (e.g. transact("foo", function() { ... }, true) ), or better imho, have transact() specify a custom transaction and introduce record() (just to avoid autoTransact()) which will specify an automatic transaction, thus having: t = undoManager.transact("lala", function() { }); t.execute(); // error, transact() with no undo() t = undoManager.record("baba", function() {}); t.onundo = function() { }; // will be ignored/error thrown, since we're on record() t.execute();
Re: [UndoManager] Re-introduce DOMTransaction interface?
Thanks for the feedback. We need more developer feedbacks on this spec. On Jul 5, 2012 1:50 PM, "Yuval Sadan" wrote: >> >> >> Passing in objects containing one or more non-callback properties is also an increaingly common pattern, and we are trying to replace legacy APIs that took lots of positional arguments with options-object based replacements (e.g. init*Event). From the point of view of a javascript author there is no difference between something like {foo:true} and {foo:function(){}}. Insisting that there should be a difference in DOM APIs because of low-level implementation concerns is doing a disservice to web authors by increasing the impedence mismatch between the DOM and javascript. >> > I read the conversation but still feel I'm stepping into other people's business; I'll still pitch in my author point-of-view: > > A. Are there any other APIs where a JS object representing an atomic piece of data is passed as an interface-less object to a DOM function? I don't think this includes options-objects, which are meant to, imo, alleviate the pain of optional arguments. > > It seems helper functions with position-based arguments are more common: addEventListener, createElement, createObjectURL, and more notably pushState/replaceState (in history, which also have to do with saving atomic records, and historical ones to that). > > B. On the other hand, are there APIs where objects with interfaces are created explicitly using the interface name? > > Sifting through the webapps docs, I found several sporadic examples of DOM-defined objects which are explicitly instantiated: > - Image, Audio, Option, > - MediaController, TextTrackCue, > - DrawingStyle, Path, > - Worker, SharedWorker, MessageChannel, XMLHttpRequest, EventSource, WebSocket. > > Of these, the closest semantic relative is TextTrackCue, and it uses positional syntax similar to what was suggested. > > Also worth mentioning is IndexedDB which is loaded with new interfaces, but not one is instantiated by authors (might be very well be wrong, just afaik). > > To sum up, as an author I vote for-- > var t = undoManager.transact("foo"); > t.onundo = function() { ... }; > OR t.setUndo(function() { }); How do you envision it should work with an automatic transaction? We need some mechanism to tell the UA "record DOM mutations while I'm calling this function". - Ryosuke
Re: [UndoManager] Re-introduce DOMTransaction interface?
> > > Passing in objects containing one or more non-callback properties is also > an increaingly common pattern, and we are trying to replace legacy APIs > that took lots of positional arguments with options-object based > replacements (e.g. init*Event). From the point of view of a javascript > author there is no difference between something like {foo:true} and > {foo:function(){}}. Insisting that there should be a difference in DOM APIs > because of low-level implementation concerns is doing a disservice to web > authors by increasing the impedence mismatch between the DOM and javascript. > > I read the conversation but still feel I'm stepping into other people's business; I'll still pitch in my author point-of-view: A. Are there any other APIs where a JS object representing an atomic piece of data is passed as an interface-less object to a DOM function? I don't think this includes options-objects, which are meant to, imo, alleviate the pain of optional arguments. It seems helper functions with position-based arguments are more common: addEventListener, createElement, createObjectURL, and more notably pushState/replaceState (in history, which also have to do with saving atomic records, and historical ones to that). B. On the other hand, are there APIs where objects with interfaces are created explicitly using the interface name? Sifting through the webapps docs, I found several sporadic examples of DOM-defined objects which are explicitly instantiated: - Image, Audio, Option, - MediaController, TextTrackCue, - DrawingStyle, Path, - Worker, SharedWorker, MessageChannel, XMLHttpRequest, EventSource, WebSocket. Of these, the closest semantic relative is TextTrackCue, and it uses positional syntax similar to what was suggested. Also worth mentioning is IndexedDB which is loaded with new interfaces, but not one is instantiated by authors (might be very well be wrong, just afaik). To sum up, as an author I vote for-- var t = undoManager.transact("foo"); t.onundo = function() { ... }; OR t.setUndo(function() { });
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 12:45 PM, James Graham wrote: > On Thu, 5 Jul 2012, Ryosuke Niwa wrote: > >> On Thu, Jul 5, 2012 at 8:08 AM, James Graham **wrote: >> >>> On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{**function () { scope.appendChild("foo"); }, 'append "foo"')); [...] > >> document.undoManager.transact(**new DOMTransaction({function () { // Draw a line on canvas }, function () { // Undraw a line }, function () { this.execute(); }, 'Draw a line' })); >>> >>> I think this proposed API looks particularly verbose and ugly. I thought >>> we wanted to make new APIs more author >>> friendly and less like refugees from Java-land. >>> >> >> >> What makes you say so? If anything, you don't have to have labels like >> execute, undo, and redo. So it's less verbose. If you >> don't like the long name like AutomaticDOMTransaction, we can come up >> with a shorter name. >> > > I think having to call a particular constructor for an object that is just > passed straight into a DOM function is verbose, and difficult to > internalise (because you have to remember the constructor name and case and > so on). I think the design with three positional arguments is much harder > to read than the design with three explicitly "named arguments" implemented > as object properties. But the alternative is having to remember labels like execute, undo, & redo. Passing in objects containing one or more non-callback properties is also > an increaingly common pattern, and we are trying to replace legacy APIs > that took lots of positional arguments with options-object based > replacements (e.g. init*Event). From the point of view of a javascript > author there is no difference between something like {foo:true} and > {foo:function(){}}. Insisting that there should be a difference in DOM APIs > because of low-level implementation concerns is doing a disservice to web > authors by increasing the impedence mismatch between the DOM and javascript. Having an explicit constructor has other advantages like making expando work. And we don't have to worry about authors modifying execute, undo, & redo after the fact because we can make them readonly (making them not readonly has some odd implications like the timing at which properties are changed matter). Also, DOM transaction object currently have two mutually exclusive functions executeAutomatic and execute, which define whether the transaction is automatic or not, and this has very weird consequences such as specifying both executeAutomatic and execute will result in an automatic transaction. Having an explicit constructor makes this interface much more clear and clean. On Thu, Jul 5, 2012 at 11:07 AM, Olli Pettay >> wrote: >> >>> We shouldn't change the UndoManager API because of implementation >>> issues, but if event based API ends up being >>> better. >>> >>> >> I don't think it's reasonable to agree on an unimplementable design. In >> theory, mutation events can be implemented correctly >> but we couldn't, so we're moving on and getting rid of it. >> > > The current deisgn is not "unimplementable", it's just slightly more work > in WebKit than you would like. I don't think it's reasonable to reject good > designs in favour of worse designs simply because the better design isn't a > perfect fit for a single implementation I don't think the current interface-less object is a good design regardless of whether it could be implemented in WebKit or not. - Ryosuke
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, 5 Jul 2012, Ryosuke Niwa wrote: On Thu, Jul 5, 2012 at 8:08 AM, James Graham wrote: On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{function () { scope.appendChild("foo"); }, 'append "foo"')); [...] document.undoManager.transact(new DOMTransaction({function () { // Draw a line on canvas }, function () { // Undraw a line }, function () { this.execute(); }, 'Draw a line' })); I think this proposed API looks particularly verbose and ugly. I thought we wanted to make new APIs more author friendly and less like refugees from Java-land. What makes you say so? If anything, you don't have to have labels like execute, undo, and redo. So it's less verbose. If you don't like the long name like AutomaticDOMTransaction, we can come up with a shorter name. I think having to call a particular constructor for an object that is just passed straight into a DOM function is verbose, and difficult to internalise (because you have to remember the constructor name and case and so on). I think the design with three positional arguments is much harder to read than the design with three explicitly "named arguments" implemented as object properties. Also, I think consistency matters a lot here. I'm not aware of any other Web-facing API that takes a pure object with callback functions. I think Olli mentioned some already, but the obvious example is event handlers which take a pure function or an object with a handleEvent property. Passing in objects containing one or more non-callback properties is also an increaingly common pattern, and we are trying to replace legacy APIs that took lots of positional arguments with options-object based replacements (e.g. init*Event). From the point of view of a javascript author there is no difference between something like {foo:true} and {foo:function(){}}. Insisting that there should be a difference in DOM APIs because of low-level implementation concerns is doing a disservice to web authors by increasing the impedence mismatch between the DOM and javascript. On Thu, Jul 5, 2012 at 11:07 AM, Olli Pettay wrote: We shouldn't change the UndoManager API because of implementation issues, but if event based API ends up being better. I don't think it's reasonable to agree on an unimplementable design. In theory, mutation events can be implemented correctly but we couldn't, so we're moving on and getting rid of it. That's true, but based on the content of this thread, not relevant to the issue at hand. The current deisgn is not "unimplementable", it's just slightly more work in WebKit than you would like. I don't think it's reasonable to reject good designs in favour of worse designs simply because the better design isn't a perfect fit for a single implementation; from time to time we all have to make larger changes to accomodate use cases that weren't considered when architecting our code (beforeunload in Opera is a case in point).
Re: [UndoManager] Re-introduce DOMTransaction interface?
On 07/05/2012 10:05 PM, Ryosuke Niwa wrote: Also, I think consistency matters a lot here. I'm not aware of any other Web-facing API that takes a pure object with callback functions. Except of course event listeners. Well, addEventListener can take an object with _a_ callback function. I don't think it's reasonable to agree on an unimplementable design. How is the current UndoManager unimplementable? It is just a bit hard in one implementation. (I must say I'm _very_ surprised to learn that JS callback objects can be so hard to implement in WebKit.) In theory, mutation events can be implemented correctly but we couldn't, so we're moving on and getting rid of it. Mutation Events is a bad API, and "implemented correctly" is not clear since there isn't a proper spec for Mutation Events. Bad APIs shouldn't be implemented. UndoManager is a different beast. I don't see anything bad how it currently handles callbacks. (But I also don't object to change it to use events if a good API is designed.) -Olli
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 8:08 AM, James Graham wrote: > On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: > >> After this change, authors can write: >> scope.undoManager.transact(new AutomaticDOMTransaction{**function () { >> scope.appendChild("foo"); >> }, 'append "foo"')); >> >> instead of: >> >> scope.undoManager.transact({**executeAutomatic: function () { >> scope.appendChild("foo"); >> }, label: 'append "foo"'}); >> >> And >> >> document.undoManager.transact(**new DOMTransaction({function () { >> // Draw a line on canvas >> }, function () { >> // Undraw a line >> }, function () { this.execute(); }, >> 'Draw a line' >> })); >> >> instead of: >> >> document.undoManager.transact(**{ execute: function () { >> // Draw a line on canvas >> }, undo: function () { >> // Undraw a line >> }, redo: function () { this.execute(); }, >> label: 'Draw a line' >> }); >> >> > I think this proposed API looks particularly verbose and ugly. I thought > we wanted to make new APIs more author friendly and less like refugees from > Java-land. > What makes you say so? If anything, you don't have to have labels like execute, undo, and redo. So it's less verbose. If you don't like the long name like AutomaticDOMTransaction, we can come up with a shorter name. Also, I think consistency matters a lot here. I'm not aware of any other Web-facing API that takes a pure object with callback functions. Changing the design here seems fine as long as it is not to something that > is worse for authors; priority of constituencies suggests that we favour > authors over implementers. I think this proposed design is worse. I would like to hear why it's worse with some logical explanation. All arguments I've heard so far are "ugly" and "verbose" but I'm not seeing either. On Thu, Jul 5, 2012 at 11:07 AM, Olli Pettay wrote: > > We shouldn't change the UndoManager API because of implementation issues, > but if event based API ends up being better. I don't think it's reasonable to agree on an unimplementable design. In theory, mutation events can be implemented correctly but we couldn't, so we're moving on and getting rid of it. - Ryosuke
Re: Quota Management API error codes
On Thu, Jul 5, 2012 at 5:11 PM, Maxime RETY wrote: > Today, we may have to guess why a request is blocked... > > Was it because the user didn't allow indexedDB ? > Was it because the user is in "private browsing mode" ? > Was it because the user reached a maximum quota ? > > If in every situation a "QuotaExceededError" is raised, then a web > application can't advise the user appropriately. Exposing all that user state is not necessarily a good idea. It all adds to fingerprinting. -- http://annevankesteren.nl/
Re: [UndoManager] Re-introduce DOMTransaction interface?
Btw, is there something unique with UndoManager which causes implementation problems in WebKit? There are plenty of other APIs not using eventlisteners which take JS callbacks: setTimeout, requestAnimationFrame, Google's File System API, PeerConnection ... Why aren't those causing problems? We shouldn't change the UndoManager API because of implementation issues, but if event based API ends up being better. On 07/05/2012 01:38 AM, Ryosuke Niwa wrote: Hi all, Sukolsak has been implementing the Undo Manager API in WebKit but the fact undoManager.transact() takes a pure JS object with callback functions is making it very challenging. The problem is that this object needs to be kept alive by either JS reference or DOM but doesn't have a backing C++ object. Also, as far as we've looked, there are no other specification that uses the same mechanism. Since I want to make the API consistent with the rest of the platform and the implementation maintainable in WebKit, I propose the following changes: * Re-introduce DOMTransaction interface so that scripts can instantiate new DOMTransaction(). * Introduce AutomaticDOMTransaction that inherits from DOMTransaction and has a constructor that takes two arguments: a function and an optional label After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{function () { scope.appendChild("foo"); }, 'append "foo"')); instead of: scope.undoManager.transact({executeAutomatic: function () { scope.appendChild("foo"); }, label: 'append "foo"'}); And document.undoManager.transact(new DOMTransaction({function () { // Draw a line on canvas }, function () { // Undraw a line }, function () { this.execute(); }, 'Draw a line' })); instead of: document.undoManager.transact({ execute: function () { // Draw a line on canvas }, undo: function () { // Undraw a line }, redo: function () { this.execute(); }, label: 'Draw a line' }); Best, Ryosuke Niwa Software Engineer Google Inc.
Re: [UndoManager] Re-introduce DOMTransaction interface?
On 07/05/2012 08:01 PM, Ojan Vafai wrote: On Thu, Jul 5, 2012 at 7:15 AM, Adam Barth mailto:w...@adambarth.com>> wrote: On Thu, Jul 5, 2012 at 1:37 AM, Olli Pettay mailto:olli.pet...@helsinki.fi>> wrote: > On 07/05/2012 08:00 AM, Adam Barth wrote: >> On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay mailto:olli.pet...@helsinki.fi>> >> wrote: >>> On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: >>> So, it is very much implementation detail. >>> >>> (And I still don't understand how a callback can be so hard in this case. >>> There are plenty of different kinds of callback objects. >>> new MutationObserver(some_callback_function_object) ) >> >> I haven't tested, by my reading of the MutationObserver implementation >> in WebKit is that it leaks. Specifically: >> >> MutationObserver --retains--> MutationCallback --retains--> >> some_callback_function_object --retains--> MutationObserver >> >> I don't see any code that breaks this cycle. > > Ok. In Gecko cycle collector breaks the cycle. But very much an > implementation detail. > >> DOM events > > Probably EventListeners, not Events. > >> have a bunch of delicate code to avoid break these >> reference cycles and avoid leaks. We can re-invent that wheel here, > > Or use some generic approach to fix such leaks. > >> but it's going to be buggy and leaky. > > In certain kinds of implementations. > >> I appreciatie that these jQuery-style APIs are fashionable at the >> moment, but API fashions come and go. If we use this approach, we'll >> need to maintain this buggy, leaky code forever. > > Implementation detail. Very much so :) Right, my point is that this style of API is difficult to implement correctly, which means authors will end up suffering low-quality implementations for a long time. On Thu, Jul 5, 2012 at 2:22 AM, Olli Pettay mailto:olli.pet...@helsinki.fi>> wrote: > But anyhow, event based API is ok to me. > In general I prefer events/event listeners over other callbacks. Great. I'd recommend going with that approach because it will let us provide authors with high-quality implementations of the spec much sooner. The downside of events is that they have a higher overhead than we originally thought was acceptable for mutation events (e.g. just computing the ancestor chain is too expensive). Now that we fire less frequently, the overhead might be OK, but it's still not great IMO. Only having a high-overhead option for any new APIs we add is problematic. I appreciate the implementation complexity concern, but I think we just need to make callbacks work. We could fire the event on the MutationObserver itself. That would be lightweight. That doesn't help though, right? new MutationObserver().addEventListener('onMutation', function() {}) vs. new MutationObserver().observe(function() {}) MutationObserver ctor takes the callback, not observe(). We're certainly not going to change MutationObserver callback handling. MutationObserver is already unprefixed and all. And in MutationObserver case having just one callback object per observer keeps things easier. In many other cases the possibility for many callbacks (eventlisteners) is preferred. But about UndoManager, I'd like to see the proposal how to handle transactions using events. -Olli
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 7:15 AM, Adam Barth wrote: > On Thu, Jul 5, 2012 at 1:37 AM, Olli Pettay > wrote: > > On 07/05/2012 08:00 AM, Adam Barth wrote: > >> On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay > >> wrote: > >>> On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: > >>> So, it is very much implementation detail. > >>> > >>> (And I still don't understand how a callback can be so hard in this > case. > >>> There are plenty of different kinds of callback objects. > >>> new MutationObserver(some_callback_function_object) ) > >> > >> I haven't tested, by my reading of the MutationObserver implementation > >> in WebKit is that it leaks. Specifically: > >> > >> MutationObserver --retains--> MutationCallback --retains--> > >> some_callback_function_object --retains--> MutationObserver > >> > >> I don't see any code that breaks this cycle. > > > > Ok. In Gecko cycle collector breaks the cycle. But very much an > > implementation detail. > > > >> DOM events > > > > Probably EventListeners, not Events. > > > >> have a bunch of delicate code to avoid break these > >> reference cycles and avoid leaks. We can re-invent that wheel here, > > > > Or use some generic approach to fix such leaks. > > > >> but it's going to be buggy and leaky. > > > > In certain kinds of implementations. > > > >> I appreciatie that these jQuery-style APIs are fashionable at the > >> moment, but API fashions come and go. If we use this approach, we'll > >> need to maintain this buggy, leaky code forever. > > > > Implementation detail. Very much so :) > > Right, my point is that this style of API is difficult to implement > correctly, which means authors will end up suffering low-quality > implementations for a long time. > > On Thu, Jul 5, 2012 at 2:22 AM, Olli Pettay > wrote: > > But anyhow, event based API is ok to me. > > In general I prefer events/event listeners over other callbacks. > > Great. I'd recommend going with that approach because it will let us > provide authors with high-quality implementations of the spec much > sooner. > The downside of events is that they have a higher overhead than we originally thought was acceptable for mutation events (e.g. just computing the ancestor chain is too expensive). Now that we fire less frequently, the overhead might be OK, but it's still not great IMO. Only having a high-overhead option for any new APIs we add is problematic. I appreciate the implementation complexity concern, but I think we just need to make callbacks work. We could fire the event on the MutationObserver itself. That would be lightweight. That doesn't help though, right? new MutationObserver().addEventListener('onMutation', function() {}) vs. new MutationObserver().observe(function() {})
Re: Quota Management API error codes
> > Sorry for being unclear. > > I would like to see the standard to include what happens when a page > requests quota using requestQuota, but the UA doesn't fulfill the request > because of some user configured policies (and not because it's just not > possible). > > This would allow a web site to display a more sensible message to the user > (e.g. "please enable storage" vs "your harddrive seems to be full") > > -jochen +1 to standardize a way to detect configured policies. Back in time, Google Gears at least raised an exception with the following message: "Page does not have permission to use Google Gears.". Today, we may have to guess why a request is blocked... Was it because the user didn't allow indexedDB ? Was it because the user is in "private browsing mode" ? Was it because the user reached a maximum quota ? If in every situation a "QuotaExceededError" is raised, then a web application can't advise the user appropriately. Being a developer of offline web applications since 4 years, I personally feel the need of such a clarification. But I don't know if it belongs to the requestQuota standard or to the standards that use the storage capability... Note: in Firefox 16 (alpha), implementers chose to raise an "InvalidStateError" when the user did not allow indexedDB at all, and a "QuotaExceededError" when the user did not allow to extend the maximum quota (50MB). -- Maxime
[Bug 17702] New: [IndexedDB editorial] IDBIndex.getKey should tell what it's doing
https://www.w3.org/Bugs/Public/show_bug.cgi?id=17702 Summary: [IndexedDB editorial] IDBIndex.getKey should tell what it's doing Product: WebAppsWG Version: unspecified Platform: All OS/Version: All Status: NEW Severity: trivial Priority: P2 Component: Indexed Database API AssignedTo: dave.n...@w3.org ReportedBy: odi...@opera.com QAContact: public-webapps-bugzi...@w3.org CC: m...@w3.org, public-webapps@w3.org IDBIndex's getKey could really benefit from a small explanation. Something like: gets the primary key of the record from referenced object store or: get the primary key of the record by looking up the indexed key At least, so people can understand why it is different from normal get(). -- Configure bugmail: https://www.w3.org/Bugs/Public/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are on the CC list for the bug.
Re: [UndoManager] Re-introduce DOMTransaction interface?
On 07/05/2012 12:38 AM, Ryosuke Niwa wrote: Hi all, Sukolsak has been implementing the Undo Manager API in WebKit but the fact undoManager.transact() takes a pure JS object with callback functions is making it very challenging. The problem is that this object needs to be kept alive by either JS reference or DOM but doesn't have a backing C++ object. Also, as far as we've looked, there are no other specification that uses the same mechanism. I am given to understand that this kind of construct is not a big problem for Opera. Since I want to make the API consistent with the rest of the platform and the implementation maintainable in WebKit, I propose the following changes: - Re-introduce DOMTransaction interface so that scripts can instantiate new DOMTransaction(). - Introduce AutomaticDOMTransaction that inherits from DOMTransaction and has a constructor that takes two arguments: a function and an optional label After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{function () { scope.appendChild("foo"); }, 'append "foo"')); instead of: scope.undoManager.transact({executeAutomatic: function () { scope.appendChild("foo"); }, label: 'append "foo"'}); And document.undoManager.transact(new DOMTransaction({function () { // Draw a line on canvas }, function () { // Undraw a line }, function () { this.execute(); }, 'Draw a line' })); instead of: document.undoManager.transact({ execute: function () { // Draw a line on canvas }, undo: function () { // Undraw a line }, redo: function () { this.execute(); }, label: 'Draw a line' }); I think this proposed API looks particularly verbose and ugly. I thought we wanted to make new APIs more author friendly and less like refugees from Java-land. Changing the design here seems fine as long as it is not to something that is worse for authors; priority of constituencies suggests that we favour authors over implementers. I think this proposed design is worse. Perhaps an event based approach is not, but I would need to see the detailed proposal.
Re: [UndoManager] Re-introduce DOMTransaction interface?
On 07/05/2012 05:15 PM, Adam Barth wrote: On Thu, Jul 5, 2012 at 1:37 AM, Olli Pettay wrote: On 07/05/2012 08:00 AM, Adam Barth wrote: On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay wrote: On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: So, it is very much implementation detail. (And I still don't understand how a callback can be so hard in this case. There are plenty of different kinds of callback objects. new MutationObserver(some_callback_function_object) ) I haven't tested, by my reading of the MutationObserver implementation in WebKit is that it leaks. Specifically: MutationObserver --retains--> MutationCallback --retains--> some_callback_function_object --retains--> MutationObserver I don't see any code that breaks this cycle. Ok. In Gecko cycle collector breaks the cycle. But very much an implementation detail. DOM events Probably EventListeners, not Events. have a bunch of delicate code to avoid break these reference cycles and avoid leaks. We can re-invent that wheel here, Or use some generic approach to fix such leaks. but it's going to be buggy and leaky. In certain kinds of implementations. I appreciatie that these jQuery-style APIs are fashionable at the moment, but API fashions come and go. If we use this approach, we'll need to maintain this buggy, leaky code forever. Implementation detail. Very much so :) Right, my point is that this style of API is difficult to implement correctly, which means authors will end up suffering low-quality implementations for a long time. My point is that it is not too difficult to implement such API correctly, it just happens to be difficult currently in one(?) implementation. On Thu, Jul 5, 2012 at 2:22 AM, Olli Pettay wrote: But anyhow, event based API is ok to me. In general I prefer events/event listeners over other callbacks. Great. I'd recommend going with that approach because it will let us provide authors with high-quality implementations of the spec much sooner. Adam
Re: [UndoManager] Re-introduce DOMTransaction interface?
On Thu, Jul 5, 2012 at 1:37 AM, Olli Pettay wrote: > On 07/05/2012 08:00 AM, Adam Barth wrote: >> On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay >> wrote: >>> On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: >>> So, it is very much implementation detail. >>> >>> (And I still don't understand how a callback can be so hard in this case. >>> There are plenty of different kinds of callback objects. >>> new MutationObserver(some_callback_function_object) ) >> >> I haven't tested, by my reading of the MutationObserver implementation >> in WebKit is that it leaks. Specifically: >> >> MutationObserver --retains--> MutationCallback --retains--> >> some_callback_function_object --retains--> MutationObserver >> >> I don't see any code that breaks this cycle. > > Ok. In Gecko cycle collector breaks the cycle. But very much an > implementation detail. > >> DOM events > > Probably EventListeners, not Events. > >> have a bunch of delicate code to avoid break these >> reference cycles and avoid leaks. We can re-invent that wheel here, > > Or use some generic approach to fix such leaks. > >> but it's going to be buggy and leaky. > > In certain kinds of implementations. > >> I appreciatie that these jQuery-style APIs are fashionable at the >> moment, but API fashions come and go. If we use this approach, we'll >> need to maintain this buggy, leaky code forever. > > Implementation detail. Very much so :) Right, my point is that this style of API is difficult to implement correctly, which means authors will end up suffering low-quality implementations for a long time. On Thu, Jul 5, 2012 at 2:22 AM, Olli Pettay wrote: > But anyhow, event based API is ok to me. > In general I prefer events/event listeners over other callbacks. Great. I'd recommend going with that approach because it will let us provide authors with high-quality implementations of the spec much sooner. Adam
Re: Quota Management API error codes
On Wed, Jul 4, 2012 at 11:21 AM, Anne van Kesteren wrote: > On Tue, Jul 3, 2012 at 2:56 PM, Jochen Eisinger > wrote: > > while reading > http://www.w3.org/TR/quota-api/#quota-handling-in-storage-api > > I wondered what the desired behavior was when the UA refuses to grant any > > quota? I think it would be nice to specify this in the standard. > > > > E.g. currently WebKit will throw a QuotaExceeded exception when a page > tries > > to write to DOM storage when DOM storage is disabled, while Firefox > throws a > > Security exception on any access to DOM storage. These inconsistencies > make > > it difficult for website authors to write apps that work when the user > > configured the UA to disable certain APIs > > That should (and is) defined in the standards that use the storage > (such as Web Storage) as it very much depends on the API what the > right solution is. > > Sorry for being unclear. I would like to see the standard to include what happens when a page requests quota using requestQuota, but the UA doesn't fulfill the request because of some user configured policies (and not because it's just not possible). This would allow a web site to display a more sensible message to the user (e.g. "please enable storage" vs "your harddrive seems to be full") -jochen > -- > http://annevankesteren.nl/ >
Re: [UndoManager] Re-introduce DOMTransaction interface?
But anyhow, event based API is ok to me. In general I prefer events/event listeners over other callbacks. On 07/05/2012 11:37 AM, Olli Pettay wrote: On 07/05/2012 08:00 AM, Adam Barth wrote: On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay wrote: On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: On Wed, Jul 4, 2012 at 5:00 PM, Olli Pettay mailto:olli.pet...@helsinki.fi>> wrote: On 07/05/2012 01:38 AM, Ryosuke Niwa wrote: Hi all, Sukolsak has been implementing the Undo Manager API in WebKit but the fact undoManager.transact() takes a pure JS object with callback functions is making it very challenging. The problem is that this object needs to be kept alive by either JS reference or DOM but doesn't have a backing C++ object. Also, as far as we've looked, there are no other specification that uses the same mechanism. I don't understand what is difficult. How is that any different to target.addEventListener("foo", { handleEvent: function() {}}) It will be very similar to that except this object is going to have 3 callbacks instead of one. The problem is that the event listener is a very special object in WebKit for which we have a lot of custom binding code. We don't want to implement a similar behavior for the DOM transaction because it's very error prone. So, it is very much implementation detail. (And I still don't understand how a callback can be so hard in this case. There are plenty of different kinds of callback objects. new MutationObserver(some_callback_function_object) ) I haven't tested, by my reading of the MutationObserver implementation in WebKit is that it leaks. Specifically: MutationObserver --retains--> MutationCallback --retains--> some_callback_function_object --retains--> MutationObserver I don't see any code that breaks this cycle. Ok. In Gecko cycle collector breaks the cycle. But very much an implementation detail. DOM events Probably EventListeners, not Events. have a bunch of delicate code to avoid break these reference cycles and avoid leaks. We can re-invent that wheel here, Or use some generic approach to fix such leaks. but it's going to be buggy and leaky. In certain kinds of implementations. I appreciatie that these jQuery-style APIs are fashionable at the moment, but API fashions come and go. If we use this approach, we'll need to maintain this buggy, leaky code forever. Implementation detail. Very much so :) Do JS callbacks cause implementation problems in Presto or Trident? -Olli Instead, we can save ourselves a lot of pain by just using events, like the rest of the web platform. Adam Since I want to make the API consistent with the rest of the platform and the implementation maintainable in WebKit, I propose the following changes: * Re-introduce DOMTransaction interface so that scripts can instantiate new DOMTransaction(). * Introduce AutomaticDOMTransaction that inherits from DOMTransaction and has a constructor that takes two arguments: a function and an optional label After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{__function () { scope.appendChild("foo"); }, 'append "foo"')); Looks somewhat odd. DOMTransaction would be just a container for a callback? Right. If we wanted, we can make DOMTransaction an event target and implement execute, undo, & redo as event listeners to further simplify the matter. That could make the code more consistent with rest of the platform, but the API would become harder to use. - Ryosuke
Re: [UndoManager] Re-introduce DOMTransaction interface?
On 07/05/2012 08:00 AM, Adam Barth wrote: On Wed, Jul 4, 2012 at 5:25 PM, Olli Pettay wrote: On 07/05/2012 03:11 AM, Ryosuke Niwa wrote: On Wed, Jul 4, 2012 at 5:00 PM, Olli Pettay mailto:olli.pet...@helsinki.fi>> wrote: On 07/05/2012 01:38 AM, Ryosuke Niwa wrote: Hi all, Sukolsak has been implementing the Undo Manager API in WebKit but the fact undoManager.transact() takes a pure JS object with callback functions is making it very challenging. The problem is that this object needs to be kept alive by either JS reference or DOM but doesn't have a backing C++ object. Also, as far as we've looked, there are no other specification that uses the same mechanism. I don't understand what is difficult. How is that any different to target.addEventListener("foo", { handleEvent: function() {}}) It will be very similar to that except this object is going to have 3 callbacks instead of one. The problem is that the event listener is a very special object in WebKit for which we have a lot of custom binding code. We don't want to implement a similar behavior for the DOM transaction because it's very error prone. So, it is very much implementation detail. (And I still don't understand how a callback can be so hard in this case. There are plenty of different kinds of callback objects. new MutationObserver(some_callback_function_object) ) I haven't tested, by my reading of the MutationObserver implementation in WebKit is that it leaks. Specifically: MutationObserver --retains--> MutationCallback --retains--> some_callback_function_object --retains--> MutationObserver I don't see any code that breaks this cycle. Ok. In Gecko cycle collector breaks the cycle. But very much an implementation detail. DOM events Probably EventListeners, not Events. have a bunch of delicate code to avoid break these reference cycles and avoid leaks. We can re-invent that wheel here, Or use some generic approach to fix such leaks. but it's going to be buggy and leaky. In certain kinds of implementations. I appreciatie that these jQuery-style APIs are fashionable at the moment, but API fashions come and go. If we use this approach, we'll need to maintain this buggy, leaky code forever. Implementation detail. Very much so :) Do JS callbacks cause implementation problems in Presto or Trident? -Olli Instead, we can save ourselves a lot of pain by just using events, like the rest of the web platform. Adam Since I want to make the API consistent with the rest of the platform and the implementation maintainable in WebKit, I propose the following changes: * Re-introduce DOMTransaction interface so that scripts can instantiate new DOMTransaction(). * Introduce AutomaticDOMTransaction that inherits from DOMTransaction and has a constructor that takes two arguments: a function and an optional label After this change, authors can write: scope.undoManager.transact(new AutomaticDOMTransaction{__function () { scope.appendChild("foo"); }, 'append "foo"')); Looks somewhat odd. DOMTransaction would be just a container for a callback? Right. If we wanted, we can make DOMTransaction an event target and implement execute, undo, & redo as event listeners to further simplify the matter. That could make the code more consistent with rest of the platform, but the API would become harder to use. - Ryosuke