fckeuspy-go/vendor/github.com/hack-pad/go-indexeddb/idb/cursor.go

197 lines
5.9 KiB
Go

//go:build js && wasm
// +build js,wasm
package idb
import (
"syscall/js"
"github.com/hack-pad/go-indexeddb/idb/internal/jscache"
"github.com/hack-pad/safejs"
)
var (
jsObjectStore safejs.Value
cursorDirectionCache jscache.Strings
)
func init() {
var err error
jsObjectStore, err = safejs.Global().Get("IDBObjectStore")
if err != nil {
panic(err)
}
}
// CursorDirection is the direction of traversal of the cursor
type CursorDirection int
const (
// CursorNext direction causes the cursor to be opened at the start of the source.
CursorNext CursorDirection = iota
// CursorNextUnique direction causes the cursor to be opened at the start of the source. For every key with duplicate values, only the first record is yielded.
CursorNextUnique
// CursorPrevious direction causes the cursor to be opened at the end of the source.
CursorPrevious
// CursorPreviousUnique direction causes the cursor to be opened at the end of the source. For every key with duplicate values, only the first record is yielded.
CursorPreviousUnique
)
func parseCursorDirection(s string) CursorDirection {
switch s {
case "nextunique":
return CursorNextUnique
case "prev":
return CursorPrevious
case "prevunique":
return CursorPreviousUnique
default:
return CursorNext
}
}
func (d CursorDirection) String() string {
switch d {
case CursorNextUnique:
return "nextunique"
case CursorPrevious:
return "prev"
case CursorPreviousUnique:
return "prevunique"
default:
return "next"
}
}
func (d CursorDirection) jsValue() safejs.Value {
return cursorDirectionCache.Value(d.String())
}
// Cursor represents a cursor for traversing or iterating over multiple records in a Database
type Cursor struct {
txn *Transaction
jsCursor safejs.Value
iterated bool // set to true when an iteration method is called, like Continue
}
func wrapCursor(txn *Transaction, jsCursor safejs.Value) *Cursor {
if txn == nil {
txn = (*Transaction)(nil)
}
return &Cursor{
txn: txn,
jsCursor: jsCursor,
}
}
// Source returns the ObjectStore or Index that the cursor is iterating
func (c *Cursor) Source() (objectStore *ObjectStore, index *Index, err error) {
jsSource, err := c.jsCursor.Get("source")
if err != nil {
return
}
if isInstance, _ := jsSource.InstanceOf(jsObjectStore); isInstance {
objectStore = wrapObjectStore(c.txn, jsSource)
} else if isInstance, _ := jsSource.InstanceOf(jsIDBIndex); isInstance {
index = wrapIndex(c.txn, jsSource)
}
return
}
// Direction returns the direction of traversal of the cursor
func (c *Cursor) Direction() (CursorDirection, error) {
direction, err := c.jsCursor.Get("direction")
if err != nil {
return 0, err
}
directionStr, err := direction.String()
return parseCursorDirection(directionStr), err
}
// Key returns the key for the record at the cursor's position. If the cursor is outside its range, this is set to undefined.
func (c *Cursor) Key() (js.Value, error) {
value, err := c.jsCursor.Get("key")
return safejs.Unsafe(value), err
}
// PrimaryKey returns the cursor's current effective primary key. If the cursor is currently being iterated or has iterated outside its range, this is set to undefined.
func (c *Cursor) PrimaryKey() (js.Value, error) {
value, err := c.jsCursor.Get("primaryKey")
return safejs.Unsafe(value), err
}
// Request returns the Request that was used to obtain the cursor.
func (c *Cursor) Request() (*Request, error) {
reqValue, err := c.jsCursor.Get("request")
if err != nil {
return nil, err
}
return wrapRequest(c.txn, reqValue), nil
}
// Advance sets the number of times a cursor should move its position forward.
func (c *Cursor) Advance(count uint) error {
c.iterated = true
_, err := c.jsCursor.Call("advance", count)
return tryAsDOMException(err)
}
// Continue advances the cursor to the next position along its direction.
func (c *Cursor) Continue() error {
c.iterated = true
_, err := c.jsCursor.Call("continue")
return tryAsDOMException(err)
}
// ContinueKey advances the cursor to the next position along its direction.
func (c *Cursor) ContinueKey(key js.Value) error {
c.iterated = true
_, err := c.jsCursor.Call("continue", key)
return tryAsDOMException(err)
}
// ContinuePrimaryKey sets the cursor to the given index key and primary key given as arguments. Returns an error if the source is not an index.
func (c *Cursor) ContinuePrimaryKey(key, primaryKey js.Value) error {
c.iterated = true
_, err := c.jsCursor.Call("continuePrimaryKey", key, primaryKey)
return tryAsDOMException(err)
}
// Delete returns an AckRequest, and, in a separate thread, deletes the record at the cursor's position, without changing the cursor's position. This can be used to delete specific records.
func (c *Cursor) Delete() (*AckRequest, error) {
reqValue, err := c.jsCursor.Call("delete")
if err != nil {
return nil, tryAsDOMException(err)
}
req := wrapRequest(c.txn, reqValue)
return newAckRequest(req), nil
}
// Update returns a Request, and, in a separate thread, updates the value at the current position of the cursor in the object store. This can be used to update specific records.
func (c *Cursor) Update(value js.Value) (*Request, error) {
reqValue, err := c.jsCursor.Call("update", value)
if err != nil {
return nil, tryAsDOMException(err)
}
return wrapRequest(c.txn, reqValue), nil
}
// CursorWithValue represents a cursor for traversing or iterating over multiple records in a database. It is the same as the Cursor, except that it includes the value property.
type CursorWithValue struct {
*Cursor
}
func newCursorWithValue(cursor *Cursor) *CursorWithValue {
return &CursorWithValue{cursor}
}
func wrapCursorWithValue(txn *Transaction, jsCursor safejs.Value) *CursorWithValue {
return newCursorWithValue(wrapCursor(txn, jsCursor))
}
// Value returns the value of the current cursor
func (c *CursorWithValue) Value() (js.Value, error) {
value, err := c.jsCursor.Get("value")
return safejs.Unsafe(value), err
}