From d913df0d7cc90da92f998963293b7247e79c74a8 Mon Sep 17 00:00:00 2001 From: David Barri Date: Sat, 4 Sep 2021 09:31:18 +1000 Subject: [PATCH 1/2] Sync IDBTransactionMode names to their JS counterparts --- src/main/scala/org/scalajs/dom/IDBTypes.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/scala/org/scalajs/dom/IDBTypes.scala b/src/main/scala/org/scalajs/dom/IDBTypes.scala index befb77c84..7fccac367 100644 --- a/src/main/scala/org/scalajs/dom/IDBTypes.scala +++ b/src/main/scala/org/scalajs/dom/IDBTypes.scala @@ -30,7 +30,7 @@ object IDBTransactionMode { * * MDN */ - val READ_ONLY = "readonly".asInstanceOf[IDBTransactionMode] + val readonly = "readonly".asInstanceOf[IDBTransactionMode] /** * Allows any operation to be performed, including ones that delete and create object @@ -40,15 +40,14 @@ object IDBTransactionMode { * * MDN */ - val VERSION_CHANGE = "versionchange".asInstanceOf[IDBTransactionMode] + val versionchange = "versionchange".asInstanceOf[IDBTransactionMode] /** * Allows reading and writing of data in existing data stores to be changed. * * MDN */ - val READ_WRITE = "readwrite".asInstanceOf[IDBTransactionMode] - + val readwrite = "readwrite".asInstanceOf[IDBTransactionMode] } /** From ccec27b121b820eba385cf6f60f354207c14d863 Mon Sep 17 00:00:00 2001 From: David Barri Date: Sat, 4 Sep 2021 10:58:54 +1000 Subject: [PATCH 2/2] Add type-safety to IDB keys --- src/main/scala/org/scalajs/dom/IDBTypes.scala | 65 ++++++++++++---- .../dom/tests/shared/CompilationTest.scala | 75 +++++++++++++++++++ 2 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 tests-shared/src/main/scala/org/scalajs/dom/tests/shared/CompilationTest.scala diff --git a/src/main/scala/org/scalajs/dom/IDBTypes.scala b/src/main/scala/org/scalajs/dom/IDBTypes.scala index 7fccac367..c99fcdc77 100644 --- a/src/main/scala/org/scalajs/dom/IDBTypes.scala +++ b/src/main/scala/org/scalajs/dom/IDBTypes.scala @@ -9,10 +9,45 @@ */ package org.scalajs.dom +import scala.annotation.nowarn +import scala.language.implicitConversions import scala.scalajs.js import scala.scalajs.js.annotation._ +import scala.scalajs.js.typedarray._ import scala.scalajs.js.| +/** number, date, string, binary, or array. + * + * Array objects, where every item is defined, is itself a valid key, and does not directly or indirectly contain itself. This includes empty arrays. Arrays can contain other arrays. + * + * https://w3c.github.io/IndexedDB/#key + * https://github.com/web-platform-tests/wpt/blob/master/IndexedDB/idb-binary-key-roundtrip.htm + */ +@js.native +sealed trait IDBKey extends js.Any + +@nowarn("cat=unused") +object IDBKey { + + type Flat = Double | js.Date | String | ArrayBuffer | ArrayBufferView | BigInt64Array | BigUint64Array | DataView | Float32Array | Float64Array | Int16Array | Int32Array | Int8Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray + + sealed trait IsKey[-A] + object IsKey { + @inline implicit def flat[A](implicit e: |.Evidence[A, Flat]): IsKey[A] = null + @inline implicit def array[A](implicit e: IsKey[A]): IsKey[js.Array[A]] = null + @inline implicit def coproduct[A, B](implicit a: IsKey[A], b: IsKey[B]): IsKey[A | B] = null + } + + @inline implicit def from[A: IsKey](a: A): IDBKey = + a.asInstanceOf[IDBKey] + + @inline implicit def undef[A: IsKey](a: A): js.UndefOr[IDBKey] = + a.asInstanceOf[js.UndefOr[IDBKey]] + + @inline implicit def undefOrLeft[A: IsKey, B](a: A): js.UndefOr[IDBKey | B] = + a.asInstanceOf[js.UndefOr[IDBKey | B]] +} + /** * IndexedDB transaction mode * Provides constants for IDB Transaction modes @@ -85,7 +120,7 @@ class IDBObjectStore extends js.Object { */ def keyPath: String = js.native - def count(key: js.Any = js.native): IDBRequest = js.native + def count(key: IDBKey = js.native): IDBRequest = js.native /** * To determine if the add operation has completed successfully, listen for the @@ -96,7 +131,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def add(value: js.Any, key: js.Any = js.native): IDBRequest = js.native + def add(value: js.Any, key: IDBKey = js.native): IDBRequest = js.native /** * Clearing an object store consists of removing all records from the object store and @@ -122,7 +157,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def put(value: js.Any, key: js.Any = js.native): IDBRequest = js.native + def put(value: js.Any, key: IDBKey = js.native): IDBRequest = js.native /** * The method sets the position of the cursor to the appropriate record, @@ -130,7 +165,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def openCursor(range: js.UndefOr[IDBKeyRange | js.Any] = js.undefined, + def openCursor(range: js.UndefOr[IDBKey | IDBKeyRange] = js.undefined, direction: js.UndefOr[ IDBCursorDirection] = js.undefined): IDBRequest = js.native @@ -140,7 +175,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def openKeyCursor(range: js.UndefOr[IDBKeyRange | js.Any] = js.undefined, + def openKeyCursor(range: js.UndefOr[IDBKey | IDBKeyRange] = js.undefined, direction: js.UndefOr[ IDBCursorDirection] = js.undefined): IDBRequest = js.native @@ -166,7 +201,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def get(key: js.Any): IDBRequest = js.native + def get(key: IDBKey): IDBRequest = js.native /** * If a value is successfully found, then a structured clone of it is created and set as @@ -174,7 +209,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def getAll(query: js.UndefOr[IDBKeyRange | js.Any] = js.undefined, + def getAll(query: js.UndefOr[IDBKey | IDBKeyRange] = js.undefined, count: js.UndefOr[Int] = js.undefined): IDBRequest = js.native /** @@ -183,7 +218,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def getAllKeys(query: js.UndefOr[IDBKeyRange | js.Any] = js.undefined, + def getAllKeys(query: js.UndefOr[IDBKey | IDBKeyRange] = js.undefined, count: js.UndefOr[Int] = js.undefined): IDBRequest = js.native /** @@ -192,7 +227,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def getKey(key: js.Any): IDBRequest = js.native + def getKey(key: IDBKey): IDBRequest = js.native /** * returns an IDBRequest object, and, in a separate thread, deletes the current @@ -200,7 +235,7 @@ class IDBObjectStore extends js.Object { * * MDN */ - def delete(key: js.Any): IDBRequest = js.native + def delete(key: IDBKey): IDBRequest = js.native } trait IDBVersionChangeEventInit extends EventInit { @@ -286,7 +321,7 @@ class IDBIndex extends js.Object { */ def objectStore: IDBObjectStore = js.native - def count(key: js.Any): IDBRequest = js.native + def count(key: IDBKey): IDBRequest = js.native /** * If you want to see how many records are between keys 1000 and 2000 in an object store, @@ -302,7 +337,7 @@ class IDBIndex extends js.Object { * * MDN */ - def getKey(key: js.Any): IDBRequest = js.native + def getKey(key: IDBKey): IDBRequest = js.native /** * Returns an IDBRequest object, and, in a separate thread, creates a cursor over the @@ -320,7 +355,7 @@ class IDBIndex extends js.Object { * * MDN */ - def get(key: js.Any): IDBRequest = js.native + def get(key: IDBKey): IDBRequest = js.native /** * The method sets the position of the cursor to the appropriate record, based on the @@ -371,7 +406,7 @@ class IDBCursor extends js.Object { * * MDN */ - def key: js.Any = js.native + def key: IDBKey = js.native /** * Returns the cursor's current effective key. If the cursor is currently being @@ -397,7 +432,7 @@ class IDBCursor extends js.Object { * * W3C */ - def continue(key: js.Any = ???): Unit = js.native + def continue(key: IDBKey = ???): Unit = js.native /** * Returns an IDBRequest object, and, in a separate thread, deletes the record at the diff --git a/tests-shared/src/main/scala/org/scalajs/dom/tests/shared/CompilationTest.scala b/tests-shared/src/main/scala/org/scalajs/dom/tests/shared/CompilationTest.scala new file mode 100644 index 000000000..ce505594b --- /dev/null +++ b/tests-shared/src/main/scala/org/scalajs/dom/tests/shared/CompilationTest.scala @@ -0,0 +1,75 @@ +package org.scalajs.dom.tests.shared + +import org.scalajs.dom._ +import scala.scalajs.js +import scala.scalajs.js.| + +trait CompilationTest { + + trait IDBKeyTests { + def o: IDBObjectStore + + locally { + import IDBKey._ + + implicitly[IsKey[Double]] + implicitly[IsKey[Int]] + implicitly[IsKey[Int | String]] + + implicitly[IsKey[js.Array[Double]]] + implicitly[IsKey[js.Array[Int]]] + implicitly[IsKey[js.Array[Int | String]]] + + implicitly[IsKey[String | js.Array[Int]]] + implicitly[IsKey[String | js.Array[Int] | Int]] + implicitly[IsKey[js.Array[String] | js.Array[Int] | Int]] + + implicitly[IsKey[js.Array[js.Array[Double]]]] + implicitly[IsKey[js.Array[js.Array[Int]]]] + implicitly[IsKey[js.Array[String | js.Array[Int]]]] + implicitly[IsKey[js.Array[String | js.Array[Int] | js.Array[String | Double]]]] + } + + o.get(123) + o.get(123.0) + o.get("qwe") + o.get(null.asInstanceOf[String | Double]) + o.get(js.Array[Int]()) + o.get(js.Array[Double]()) + o.get(js.Array[String | Double]()) + o.get(js.Array[js.Array[Double]]()) + o.get(js.Array[js.Array[String | Double]]()) + o.get(js.Array[String | js.Array[String | Double]]()) + o.get(js.Array[js.Array[String | Double] | String]()) + o.get(js.Array[String | js.Array[String | Double] | String]()) + o.get(js.Array[js.Array[js.Date | Double] | js.Array[String | Double] | js.Array[String | js.Date]]()) + + o.getAll(123) + o.getAll(123.0) + o.getAll("qwe") + o.getAll(null.asInstanceOf[String | Double]) + o.getAll(js.Array[Int]()) + o.getAll(js.Array[Double]()) + o.getAll(js.Array[String | Double]()) + o.getAll(js.Array[js.Array[Double]]()) + o.getAll(js.Array[js.Array[String | Double]]()) + o.getAll(js.Array[String | js.Array[String | Double]]()) + o.getAll(js.Array[js.Array[String | Double] | String]()) + o.getAll(js.Array[String | js.Array[String | Double] | String]()) + o.getAll(js.Array[js.Array[js.Date | Double] | js.Array[String | Double] | js.Array[String | js.Date]]()) + + 123: js.UndefOr[IDBKey] + 123.0: js.UndefOr[IDBKey] + "qwe": js.UndefOr[IDBKey] + null.asInstanceOf[String | Double]: js.UndefOr[IDBKey] + js.Array[Int](): js.UndefOr[IDBKey] + js.Array[Double](): js.UndefOr[IDBKey] + js.Array[String | Double](): js.UndefOr[IDBKey] + js.Array[js.Array[Double]](): js.UndefOr[IDBKey] + js.Array[js.Array[String | Double]](): js.UndefOr[IDBKey] + js.Array[String | js.Array[String | Double]](): js.UndefOr[IDBKey] + js.Array[js.Array[String | Double] | String](): js.UndefOr[IDBKey] + js.Array[String | js.Array[String | Double] | String](): js.UndefOr[IDBKey] + js.Array[js.Array[js.Date | Double] | js.Array[String | Double] | js.Array[String | js.Date]](): js.UndefOr[IDBKey] + } +}