- From: Ian Hickson <ian@hixie.ch>
- Date: Tue, 13 Jan 2009 09:40:05 +0000 (UTC)
On Sun, 18 May 2008, Maciej Stachowiak wrote: > On May 18, 2008, at 3:18 PM, Brady Eidson wrote: > > > > While I'm on the topic, I'm also curious about that [XXX] placeholder. > > There's a bug in WebKit's bugzilla pointing out that the IE8 beta and > > Firefox 2 both support `delete storage.keyName` syntax as an alias for > > `storage.removeItem(keyName)` > > > > I'm taking a guess here and assuming supporting the `delete` syntax is > > the implied concept behind [XXX] > > WebKit's JavaScript engine doesn't currently have the ability to run > custom code when a property is deleted. It would be a significant > challenge to add this capability and possibly a performance regression; > and no other DOM-related spec requires this, even when there is > NameGetter or IndexGetter behavior. For example NodeLists and > HTMLCollections do not let you delete by name to remove the item (I'm > not sure what that would even mean). So I'd prefer not to have to > introducethis concept just for this one case. On Sun, 18 May 2008, Brady Eidson wrote: > > WebKit has the ability to add custom property deletion on a per-class > basis - therefore not slowing down the common case at all. That's how I > fixed the bug to make us compatible with IE8 and Firefox for now as this > debate gets underway... On Mon, 19 May 2008, Geoffrey Garen wrote: > > It is *very* weird, and therefore not a "useful shorthand." > > In JavaScript, "delete" means "remove this property / interface from > this JavaScript object." I can't think of any context in which it means > anything else. > > For example, "delete node.parentNode" attempts to remove the > "parentNode" property from "node". It does not remove "parentNode" from > the document or anything like that. > > "delete window" attempts to remove the "window" property from the global > object. It does not close the window or anything like that. > > In other words, you can be certain that "delete" is a simple operation > with a consistent side-effect. > > As a JavaScript programmer, I would find it very difficult to reason > about objects that might or might not change the behavior of the > "delete" operator. One reason i would find it very difficult is that > operator overloading does not exist in JavaScript at all, so to > understand this one API, I would need to understand a vast corpus of > programming language goobery that is not at all covered in any > JavaScript manual. Another reason I would find it very difficult is that > the overloaded meaning of "delete" here ("remove persistent storage from > disk") is far afield from the original meaning ("remove interface from > temporary object in memory"). To give you an analogy, even in C++, where > you're allowed to overload operator delete, if you overloaded operator > delete to mean "do not free this object's memory, but do delete the file > it references from the file system", well, let's just say that your > patch would not pass code review with any of your four reviewers :). > > I am not sure if any JS decoration or collection libraries depend on the > canonical behavior of operator delete, but if they do, I would hate for > them all to have to ship with the asterisk, "BEWARE: do NOT use this > decoration / collection library with that one weird DOM object that > interprets 'delete' to mean 'remove important data from the user's > disk'". Oy! On Mon, 19 May 2008, Brady Eidson wrote: > > I'm unsure if you have the proper background with the Storage interface > that is in question here. I'm guessing that the reason that Firefox 2 > and IE8 support the "modified" behavior of delete for Storage items is > because the "way of thinking about Storage items" we're trying to get > across meets most of the expectations of manipulating properties that > you lay out below. > > On May 19, 2008, at 3:18 PM, Geoffrey Garen wrote: > > > > In JavaScript, "delete" means "remove this property / interface from > > this JavaScript object." I can't think of any context in which it > > means anything else. > > The spec makes it clear that storage items and properties on the Storage > object are interchangeable. > > `storage.foo = "bar"` happens to be equivalent to > `storage.setItem("foo", "bar")`, but is also no different from > `someRandomObject.foo = "bar"` as far as keeping a collection of > properties on an object. > > This also applies for enumeration, etc. > > Equivalently and more relevant to the discussion, `delete storage.foo` > happens to be equivalent to `storage.removeItem("foo")`, but is also > *little* different from `delete someRandomObject.foo` > > > For example, "delete node.parentNode" attempts to remove the > > "parentNode" property from "node". It does not remove "parentNode" > > from the document or anything like that. > > > > "delete window" attempts to remove the "window" property from the > > global object. It does not close the window or anything like that. > > In the SessionStorage case, this applies with zero caveats. In the > LocalStorage case, it applies with the caveat that "all of the > properties you set on this object will still be on this object's analog > the next time you restart the browser and come back to this page" > > And that's the really weird thing, I think - window.localStorage can be > thought of exactly like every other javascript object, except it is not > temporary. It gets created once and maintains it's state over browser > launches. We're already breaking the javascript-assumption-mold when > you get into that mindset. > > Neither IE8 or FFX have implemented LocalStorage in a release yet, so > perhaps they would not support the syntax for LocalStorage, and only > support it for SessionStorage. Of course that would be even weirder, > having 2 concrete implementations of the same interface have "API > incompatibilities" > > > In other words, you can be certain that "delete" is a simple operation > > with a consistent side-effect. > > > > As a JavaScript programmer, I would find it very difficult to reason > > about objects that might or might not change the behavior of the > > "delete" operator. > > Is the behavior of the delete operator "remove the property from the > object" or is it actually "remove the property from the object with zero > other detectable side effects"? > > > One reason i would find it very difficult is that operator overloading > > does not exist in JavaScript at all, so to understand this one API, I > > would need to understand a vast corpus of programming language goobery > > that is not at all covered in any JavaScript manual. > > I think this is a pretty shameful exaggeration ;) > > > Another reason I would find it very difficult is that the overloaded > > meaning of "delete" here ("remove persistent storage from disk") is > > far afield from the original meaning ("remove interface from temporary > > object in memory"). > > The overloaded meaning of "delete" here is "remove interface from > temporary object in memory, as well as the persistent record of its > existence." Still different from the original meaning, but not "far > afield" different. > > > To give you an analogy, even in C++, where you're allowed to overload > > operator delete, if you overloaded operator delete to mean "do not > > free this object's memory, but do delete the file it references from > > the file system", well, let's just say that your patch would not pass > > code review with any of your four reviewers :). > > But if you overloaded the delete operator to free the object's memory > *and* delete its referenced files from the file system, you'd be using > the operator overloading in its intended capacity. > > > I am not sure if any JS decoration or collection libraries depend on > > the canonical behavior of operator delete, but if they do, I would > > hate for them all to have to ship with the asterisk, "BEWARE: do NOT > > use this decoration / collection library with that one weird DOM > > object that interprets 'delete' to mean 'remove important data from > > the user's disk'". Oy! > > At the same time, why not be concerned that such a collection library > happens to expose the exact same API interface that the Storage object > exposes, and now that library should carry the same warning saying > "BEWARE: do NOT use this collection library with that one weird DOM > object that interprets 'clear()' to mean 'remove important data from the > user's disk'? > > The fact that we're giving scripts the ability to directly manipulate > data on the users disk is already a jump-off-a-bridge as far as I'm > concerned. Shouldn't a script writer using LocalStorage use due > diligence to make sure his data is actually safe as expected? On Mon, 19 May 2008, Maciej Stachowiak wrote: > > I think the analogy between delete in C++ and delete in JavaScript is > strained. First of all, the two delete operators do totally different > things. Second, C++ supports general operator overloading for nearly > every operator. The right analogy would be removing objects from > collections, and C++ does not have a special operator for that. > > (But as a side note I think it would be poor style for C++ code to > overload operator delete to remove files from the filesystem. The right > place to do additional resource management would be the destructor.) > > I do agree that the spec should define a single interoperable behavior > and we should all converge. On Tue, 20 May 2008, Kristof Zelechovski wrote: > > Suppose you successfully delete a property of an object that gets > ultimately persisted that object on the server using XMLHttpRequest with > JSON. Your action of deleting the property is absolutely legal and it > undoubtedly has side effects. How is it different from the local > storage case, except that it is persisted implicitly by the session > manager? > > In other words, deleting a property from local storage does not change > anything in persistent memory by itself; it is the session manager that > executes the change afterwards. It is possible because the local > storage belongs to the global state. The operator delete is not > overloaded. On Mon, 19 May 2008, Maciej Stachowiak wrote: > > I looked into this and in all other cases we use an override of delete > for the following effects: > > - Special case for Arrays since they store some of their properties > differently. > - Prevent deletion (though it would be better in most of these cases to > just rely on DontDelete attributes)/ > - Cross-site scripting security checks on delete. > > I think the Storage case would be more complicated than this, because it > dispatches an event and so can run arbitrary JavaScript code. I think > our JS interpreter is likely not prepared for "delete" executing > arbitrary JS code, and so may crash when this happens. We can fix it, > but I think delete having special behavior is not that great from the > point of design. > > Comparing conciseness and familiarity: > > storage.keyName > storage.getItem('keyName') > > storage.keyName = 'value'; > storage.setItem('keyName', 'value'); > > delete storage.keyName; > storage.removeItem('keyName'); > > The getter seems like the biggest relative increase in conciseness, and > the getter and setter will both be much more familiar with operator > syntax. But delete is fairly rarely used (and unlike getters and setters > does not allow overriding at the JS level in many implementations) so > the syntax is not much more familiar. The improvement in conciseness is > also less. > > We should also keep in mind that overloading operators is kind of a big > deal and should not be done lightly. If the HTML5 spec required custom > behavior for * or && for certain objects rather than following the JS > rules I think we would all be pretty concerned. > > So I'd rather avoid messing with the (relative) purity of the delete > operator. On Tue, 20 May 2008, Robert O'Callahan wrote: > > If "storage.keyName = 'value';" can create a new storage item > (persistently), won't authors expect "delete storage.keyName;" to remove > it (persistently), as a matter of consistency? > > If overloading "delete" is too quirky or too hard to implement, then it > seems none of the other shorthands should be allowed either. On Mon, 19 May 2008, Maciej Stachowiak wrote: > > Many objects in the DOM implement custom name getters (for instance > NodeList) and a few even implement custom name setters > (CSSStyleDeclaration, at least the way it is done in WebKit) but no one > has clamored for a custom deleter or expected delete to work "as a > matter of consistency" or been confused that "style.opacity = 0" is > allowed but "delete style.opacity" is not. So I would say the available > evidence argues against your conclusions. On Mon, 19 May 2008, Brady Eidson wrote: > > I am a lot more swayed by this argument against adoption. > > At this point, my concerns are not of a technical nature, but rather of > a "real life web" nature - either you force FFX and IE8 to remove it, > you have others adopt it, or the spec introduces a de facto > incompatibility on the web. > > I have no solution, only this particular awareness of the problem. Since we have implementations, and implementors don't seem willing to remove it, I haven't removed the 'delete' functionality for Storage. I have, however, removed the similar functionality in UndoManager, lest someone implement it. On Tue, 20 May 2008, Maciej Stachowiak wrote: > Ian wrote: > > > > Originally, I wanted Storage objects to be indistinguishable from > > Object objects in JS, and native hash or collection objects in other > > bindings. Conceptually, that's what these objects are -- native > > name/value pair collections that happen to be mapped to non-volatile > > storage (or somewhat- volatile storage, in the case of > > sessionStorage). > > Normal objects don't fire DOM events when you change their properties (I > imagine the same may be true of native hash objects in at least some > languages), so the indistinguishability only goes so far. Well, .watch() supported by some UAs somewhat goes against this. But ok. > > I'd also like the "delete" operator to work on DOMStringMap (for the > > dataset object -- calling 'delete' on that has the side-effect of > > removing the underlying attribute) and UndoManager (where the > > side-effect is to remove the entry and renumber the following entries, > > so maybe that's not such a good idea after all), for what it's worth. > > If we want to decide that we're not supporting this, we should decide > > that before implementations of those come about. > > Those both sound suboptimal to me. UndoManager because it remove more > than the one item, and DOMStringMap because (a) you can't delete from > NamedNodeMap to remove an attribute so it would be inconsistent and (b) > removing an attribute causes a mutation event to fire and thus runs > arbitrary code (creating the same problem of 'delete' running arbitrary > code as Storage). > > > For DOMStringMap, my intention was to not provide methods at all, and > > only provide the JS-native mechanisms. > > A bold choice, but I would not recommend it as the sole available > mechanism. See above for UndoManager, but for DOMStringMap I don't want to add any other mechanisms, because they introduce name clashes. Right now the IDL for DOMStringMap is: [NameCreator, NameDeleter, NameGetter, NameSetter] interface DOMStringMap {}; It basically emulates a JS Object. It's intended only for JS. I don't see why this is a bad idea. -- Ian Hickson U+1047E )\._.,--....,'``. fL http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Received on Tuesday, 13 January 2009 01:40:05 UTC