Bug 17236 - Ambiguity in IDBTransaction.error around 'done' state
Summary: Ambiguity in IDBTransaction.error around 'done' state
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: Indexed Database API (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: This bug has no owner yet - up for the taking
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-05-29 16:11 UTC by Alec Flett
Modified: 2012-07-15 09:20 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alec Flett 2012-05-29 16:11:56 UTC
The spec says:
When the done flag is true, getting this property must return the error of the request that caused the transaction to be aborted. [...] When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.

The ambiguity here is that the 'done flag' is technically something that resides on the request, not the transaction. After the transaction itself is complete, the 'error' attribute should be the error that caused the transaction to abort, if any. So the question is, which 'done' flag does this correspond to - the done flag on the current request, the done flag on the request that caused the abort, or some other 'done' state about the transaction itself.

An example:

transaction = ...
transaction.objectStores("foo").put(badValue).onerror = function(event) {
  // can I access transaction.error here?

  // the request has its own error though.
  requestError = event.target.error;

  transaction.objectStores("foo").put(goodValue).onsuccess =function(event) {
  // can I access transaction.error here? If so, is it requestError, or is it null?
  }
}

transaction.objectStores("foo").put(goodValue).onsuccess = 

As a consumer of this interface, I'd expect the transaction's error property to be set early - i.e. available as soon as the error handler fires, above, and then I'd expect it to remain unchanged for the duration of the rest of the transaction. But I can see arguments against that. For instance, what happens if preventDefault() is called? we need to avoid setting the error in that case.. I think. So that would argue for some kind of 'done' flag / state for the transaction itself.
Comment 1 Joshua Bell 2012-07-12 18:09:05 UTC
Suggested new text (with _foo_ meaning definition link):

If this _transaction_ is not finished, getting this property must throw a DOMException of type InvalidStateError. If the transaction was committed, the property returns null. If the transaction was aborted due to an error event fired at a _request_, then getting this property must return that error. Otherwise, the error must contain the reasons for the transaction failure (e.g. QuotaExceededError, UnknownError).
Comment 2 Jonas Sicking 2012-07-12 19:20:04 UTC
Spec definitely has wrong text here.

The behavior I think we should have is the one I believe I detailed in my proposal around error handling to the list a while ago (and which received general agreement). Basically:

transaction.error returns null when a transaction is created (i.e. accessing transaction.error does not throw, unlike request.error).

If a request fails, transaction.error remains null while firing the error event on the request, and while that error event bubbles to the to the transaction and the database.

If the event isn't preventDefault'ed, transaction.error is set to the appropriate, non-null, error and an "abort" event is fired on the transaction.
Comment 3 Jonas Sicking 2012-07-12 19:27:00 UTC
Hmm.. I think it would be good to avoid throwing for this property.

Right now accessing the .error property is the only way to check if a transaction has been aborted (though it's not perfect since if you manually abort a transaction then it'll remain null).

For request.error it's pretty easy to avoid accessing request.error/request.result by simply waiting for the success/error event to fire.

On a transaction this might be more tricky since you might in the error event from a request know if the transaction has been aborted or not, to avoid placing more requests against it.

Right now the only way to do that is to check transaction.error
Comment 4 Joshua Bell 2012-07-12 19:33:49 UTC
I'm fine with not throwing on access.

Apart from an explicit call to abort(), should error remain null if transaction is aborted for reasons unrelated to a request (e.g. quota error during commit)?
Comment 5 Jonas Sicking 2012-07-12 19:42:54 UTC
I definitely think we need to set transaction.error to a non-null value even when a transaction is aborted for reasons unrelated to a request. Setting transaction.error to a non-null value is the only way the page can know why the transaction was aborted in that case. I.e. if it was due to IO errors, or due to quota errors.
Comment 6 Jonas Sicking 2012-07-15 09:20:48 UTC
http://dvcs.w3.org/hg/IndexedDB/rev/aab14b0951ca