import FDBObjectStore from"./FDBObjectStore.js";import FDBRequest from"./FDBRequest.js";import{AbortError,InvalidStateError,NotFoundError,TransactionInactiveError}from"./lib/errors.js";import FakeDOMStringList from"./lib/FakeDOMStringList.js";import FakeEvent from"./lib/FakeEvent.js";import FakeEventTarget from"./lib/FakeEventTarget.js";import{queueTask}from"./lib/scheduling.js";class FDBTransaction extends FakeEventTarget{_state="active";_started=!1;_rollbackLog=[];_objectStoresCache=new Map;error=null;onabort=null;oncomplete=null;onerror=null;_requests=[];constructor(storeNames,mode,db){super(),this._scope=new Set(storeNames),this.mode=mode,this.db=db,this.objectStoreNames=new FakeDOMStringList(...Array.from(this._scope).sort())}_abort(errName){for(const f of this._rollbackLog.reverse())f();if(null!==errName){const e=new DOMException(void 0,errName);this.error=e}for(const{request:request}of this._requests)if("done"!==request.readyState&&(request.readyState="done",request.source)){request.result=void 0,request.error=new AbortError;const event=new FakeEvent("error",{bubbles:!0,cancelable:!0});event.eventPath=[this.db,this],request.dispatchEvent(event)}queueTask((()=>{const event=new FakeEvent("abort",{bubbles:!0,cancelable:!1});event.eventPath=[this.db],this.dispatchEvent(event)})),this._state="finished"}abort(){if("committing"===this._state||"finished"===this._state)throw new InvalidStateError;this._state="active",this._abort(null)}objectStore(name){if("active"!==this._state)throw new InvalidStateError;const objectStore=this._objectStoresCache.get(name);if(void 0!==objectStore)return objectStore;const rawObjectStore=this.db._rawDatabase.rawObjectStores.get(name);if(!this._scope.has(name)||void 0===rawObjectStore)throw new NotFoundError;const objectStore2=new FDBObjectStore(this,rawObjectStore);return this._objectStoresCache.set(name,objectStore2),objectStore2}_execRequestAsync(obj){const source=obj.source,operation=obj.operation;let request=Object.hasOwn(obj,"request")?obj.request:null;if("active"!==this._state)throw new TransactionInactiveError;return request||(source?(request=new FDBRequest,request.source=source,request.transaction=source.transaction):request=new FDBRequest),this._requests.push({operation:operation,request:request}),request}_start(){let operation,request;for(this._started=!0;this._requests.length>0;){const r=this._requests.shift();if(r&&"done"!==r.request.readyState){request=r.request,operation=r.operation;break}}if(request&&operation){if(request.source){let defaultAction,event;try{const result=operation();request.readyState="done",request.result=result,request.error=void 0,"inactive"===this._state&&(this._state="active"),event=new FakeEvent("success",{bubbles:!1,cancelable:!1})}catch(err){request.readyState="done",request.result=void 0,request.error=err,"inactive"===this._state&&(this._state="active"),event=new FakeEvent("error",{bubbles:!0,cancelable:!0}),defaultAction=this._abort.bind(this,err.name)}try{event.eventPath=[this.db,this],request.dispatchEvent(event)}catch(err){throw"committing"!==this._state&&this._abort("AbortError"),err}event.canceled||defaultAction&&defaultAction()}else operation();queueTask(this._start.bind(this))}else if("finished"!==this._state&&(this._state="finished",!this.error)){const event=new FakeEvent("complete");this.dispatchEvent(event)}}commit(){if("active"!==this._state)throw new InvalidStateError;this._state="committing"}toString(){return"[object IDBRequest]"}}export default FDBTransaction;