| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- //go:build js && wasm
- // +build js,wasm
- package idb
- import (
- "context"
- "fmt"
- "log"
- "github.com/hack-pad/safejs"
- )
- // OpenDBRequest provides access to the results of requests to open or delete databases (performed using Factory.open and Factory.DeleteDatabase).
- type OpenDBRequest struct {
- *Request
- }
- // Upgrader is a function that can upgrade the given database from an old version to a new one.
- type Upgrader func(db *Database, oldVersion, newVersion uint) error
- func newOpenDBRequest(ctx context.Context, req *Request, upgrader Upgrader) (*OpenDBRequest, error) {
- ctx, cancel := context.WithCancel(ctx)
- err := req.ListenSuccess(ctx, func() {
- defer cancel()
- err := openDBListenSuccess(req)
- if err != nil {
- panic(err)
- }
- })
- if err != nil {
- return nil, err
- }
- upgrade, err := safejs.FuncOf(func(this safejs.Value, args []safejs.Value) interface{} {
- err := openDBUpgradeNeeded(req, upgrader, args)
- if err != nil {
- panic(err)
- }
- return nil
- })
- if err != nil {
- return nil, err
- }
- _, err = req.jsRequest.Call(addEventListener, "upgradeneeded", upgrade)
- if err != nil {
- return nil, tryAsDOMException(err)
- }
- go func() {
- <-ctx.Done()
- _, err := req.jsRequest.Call(removeEventListener, "upgradeneeded", upgrade)
- if err != nil {
- panic(err)
- }
- upgrade.Release()
- }()
- return &OpenDBRequest{req}, nil
- }
- func openDBListenSuccess(req *Request) error {
- jsDB, err := req.result()
- if err != nil {
- return err
- }
- versionChange, err := safejs.FuncOf(func(safejs.Value, []safejs.Value) interface{} {
- log.Println("Version change detected, closing DB...")
- _, closeErr := jsDB.Call("close")
- if closeErr != nil {
- log.Println("Error closing DB:", closeErr)
- }
- return nil
- })
- if err != nil {
- return err
- }
- _, err = jsDB.Call(addEventListener, "versionchange", versionChange)
- return tryAsDOMException(err)
- }
- func openDBUpgradeNeeded(req *Request, upgrader Upgrader, args []safejs.Value) error {
- event := args[0]
- jsDatabase, err := req.result()
- if err != nil {
- return err
- }
- db := wrapDatabase(jsDatabase)
- oldVersionValue, err := event.Get("oldVersion")
- if err != nil {
- return err
- }
- oldVersion, err := oldVersionValue.Int()
- if err != nil {
- return err
- }
- newVersionValue, err := event.Get("newVersion")
- if err != nil {
- return err
- }
- newVersion, err := newVersionValue.Int()
- if err != nil {
- return err
- }
- if oldVersion < 0 || newVersion < 0 {
- return fmt.Errorf("Unexpected negative oldVersion or newVersion: %d, %d", oldVersion, newVersion)
- }
- return upgrader(db, uint(oldVersion), uint(newVersion))
- }
- // Result returns the result of the request. If the request failed and the result is not available, an error is returned.
- func (o *OpenDBRequest) Result() (*Database, error) {
- db, err := o.Request.result()
- if err != nil {
- return nil, err
- }
- return wrapDatabase(db), nil
- }
- // Await waits for success or failure, then returns the results.
- func (o *OpenDBRequest) Await(ctx context.Context) (*Database, error) {
- db, err := o.Request.await(ctx)
- if err != nil {
- return nil, err
- }
- return wrapDatabase(db), nil
- }
|