- From: Jonas Sicking <jonas@sicking.cc>
- Date: Wed, 30 Jun 2010 18:17:30 -0700
- To: Webapps WG <public-webapps@w3.org>
Hi All, Currently the IndexedDB specification is silent on what should happen if IDBObjectStore.add, IDBObjectStore.put, IDBObjectStore.remove, IDBCursor.update or IDBCursor.remove() is called from a READ_ONLY transaction. There are two possible ways we can handle this: 1. We can throw an exception. 2. We can return a IDBRequest object and asynchronously fire a 'error' event on this object. The advantage of 1 is that we pretty much know that this was an error due to a bug in the web page, and we can always know this synchronously without having to consult the database. Throwing an error means that all the existing infrastructure for error handling with automatically kick in. For example any higher-level try/catch constructs will have an opportunity to catch the error. Implementations generally report uncaught exceptions to an error log. The browser will fire an 'error' event on the window which the page can use for further logging. Firing an error event on the other hand does not allow the browser to automatically log the error in a console as the page hasn't yet gotten a chance to handle it. The advantage of 2 is that this is consistent with other error conditions, such as writing duplicate keys, disk errors during writing the database to disk, internal errors in the database, etc. While consistency, and only needing to check for errors one way, is certainly good arguments, I would argue that people won't need to check for calling-add-on-read-only-transactions. For properly written code it's not an error that will occur, and thus there is no need to check for it. In fact, you probably are generally better off letting the exception bubble all the way up and get logged or caught by generic error handlers. Additionally, the structured clone algorithm, which defines that an exception should synchronously be thrown if the object is malformed, for example if it consists of a cyclic graph. So .add/.put/.update can already throw under certain circumstances. Also compare to if we were using a different API strategy of making objectStores and cursors returned from READ_ONLY transactions not have mutating functions. In this case if someone tried to call .put(), that also would result in a exception from the JS interpreter stating that you're calling a function that doesn't exist. So I would argue that we should throw for at least all transaction violations. I.e. whenever you try to perform an action not allowed by the current transaction. This would also cover the case of calling createObjectStore/removeObjectStore/createIndex/removeIndex during a non-setVersion-transaction. There is also another case where synchronously know that an error will be reported. We could throw when IDBCursor.update() is called when the underlying object store uses in-line keys and the property at the key path does not match the key in this cursor's position. In this case we similarly immediately know that there is an error without having to consult the database. We also generally can be sure that there is a bug in the web page which would benefit from being reported like other bugs are. And like stated above, IDBCursor.update() can already throw if the passed in object can't be structurally cloned. Jeremy previously asked if there was a test we could use to clearly/intuitively break error conditions into two groups. Ones that cause exceptions to be thrown, and ones that cause error events to be fired. I would say that errors that do not depend on what data is in the database, but rather are clearly due to errors at the call site should throw an exception. Let me know what you think. / Jonas
Received on Thursday, 1 July 2010 01:18:23 UTC