[whatwg] WebIDL vs HTML5 storage changes - delete behavior
Ian Hickson
ian at hixie.ch
Tue Jan 13 01:40:05 PST 2009
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. `._.-(,_..'--(,_..'`-.;.'
More information about the whatwg
mailing list