script: Initialize IDBCursor and IDBCursorWithValue interfaces (#38850)

Testing: Update WPT test expectation
Fixes: Part of #38111

---------

Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This commit is contained in:
Kingsley Yung 2025-08-30 22:33:01 +08:00 committed by GitHub
parent 0ac8d06053
commit 4571cc1b3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 302 additions and 138 deletions

View file

@ -0,0 +1,176 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::Cell;
use dom_struct::dom_struct;
use js::jsapi::Heap;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::MutableHandleValue;
use net_traits::indexeddb_thread::{IndexedDBKeyRange, IndexedDBKeyType};
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::{
IDBCursorDirection, IDBCursorMethods,
};
use crate::dom::bindings::codegen::UnionTypes::IDBObjectStoreOrIDBIndex;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::globalscope::GlobalScope;
use crate::dom::idbindex::IDBIndex;
use crate::dom::idbobjectstore::IDBObjectStore;
use crate::dom::idbrequest::IDBRequest;
use crate::dom::idbtransaction::IDBTransaction;
use crate::indexed_db::key_type_to_jsval;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
#[derive(JSTraceable, MallocSizeOf)]
#[expect(unused)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
pub(crate) enum ObjectStoreOrIndex {
ObjectStore(Dom<IDBObjectStore>),
Index(Dom<IDBIndex>),
}
#[dom_struct]
pub(crate) struct IDBCursor {
reflector_: Reflector,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-transaction>
transaction: Dom<IDBTransaction>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-range>
#[no_trace]
range: IndexedDBKeyRange,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-source>
source: ObjectStoreOrIndex,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-direction>
direction: IDBCursorDirection,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-position>
#[no_trace]
position: DomRefCell<Option<IndexedDBKeyType>>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-key>
#[no_trace]
key: DomRefCell<Option<IndexedDBKeyType>>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-value>
#[ignore_malloc_size_of = "mozjs"]
value: Heap<JSVal>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-got-value-flag>
got_value: Cell<bool>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-object-store-position>
#[no_trace]
object_store_position: DomRefCell<Option<IndexedDBKeyType>>,
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-key-only-flag>
key_only: bool,
/// <https://w3c.github.io/IndexedDB/#cursor-request>
request: MutNullableDom<IDBRequest>,
}
impl IDBCursor {
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new_inherited(
transaction: &IDBTransaction,
direction: IDBCursorDirection,
got_value: bool,
source: ObjectStoreOrIndex,
range: IndexedDBKeyRange,
key_only: bool,
) -> IDBCursor {
IDBCursor {
reflector_: Reflector::new(),
transaction: Dom::from_ref(transaction),
range,
source,
direction,
position: DomRefCell::new(None),
key: DomRefCell::new(None),
value: Heap::default(),
got_value: Cell::new(got_value),
object_store_position: DomRefCell::new(None),
key_only,
request: Default::default(),
}
}
#[expect(unused)]
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
global: &GlobalScope,
transaction: &IDBTransaction,
direction: IDBCursorDirection,
got_value: bool,
source: ObjectStoreOrIndex,
range: IndexedDBKeyRange,
key_only: bool,
can_gc: CanGc,
) -> DomRoot<IDBCursor> {
reflect_dom_object(
Box::new(IDBCursor::new_inherited(
transaction,
direction,
got_value,
source,
range,
key_only,
)),
global,
can_gc,
)
}
pub(crate) fn value(&self, mut out: MutableHandleValue) {
out.set(self.value.get());
}
/// <https://www.w3.org/TR/IndexedDB-2/#cursor-effective-key>
pub(crate) fn effective_key(&self) -> Option<IndexedDBKeyType> {
match &self.source {
ObjectStoreOrIndex::ObjectStore(_) => self.position.borrow().clone(),
ObjectStoreOrIndex::Index(_) => self.object_store_position.borrow().clone(),
}
}
}
impl IDBCursorMethods<crate::DomTypeHolder> for IDBCursor {
/// <https://www.w3.org/TR/IndexedDB-2/#dom-idbcursor-source>
fn Source(&self) -> IDBObjectStoreOrIDBIndex {
match &self.source {
ObjectStoreOrIndex::ObjectStore(source) => {
IDBObjectStoreOrIDBIndex::IDBObjectStore(source.as_rooted())
},
ObjectStoreOrIndex::Index(source) => {
IDBObjectStoreOrIDBIndex::IDBIndex(source.as_rooted())
},
}
}
/// <https://www.w3.org/TR/IndexedDB-2/#dom-idbcursor-direction>
fn Direction(&self) -> IDBCursorDirection {
self.direction
}
/// <https://www.w3.org/TR/IndexedDB-2/#dom-idbcursor-key>
fn Key(&self, cx: SafeJSContext, mut value: MutableHandleValue) {
match self.key.borrow().as_ref() {
Some(key) => key_type_to_jsval(cx, key, value),
None => value.set(UndefinedValue()),
}
}
/// <https://www.w3.org/TR/IndexedDB-2/#dom-idbcursor-primarykey>
fn PrimaryKey(&self, cx: SafeJSContext, mut value: MutableHandleValue) {
match self.effective_key() {
Some(effective_key) => key_type_to_jsval(cx, &effective_key, value),
None => value.set(UndefinedValue()),
}
}
/// <https://w3c.github.io/IndexedDB/#dom-idbcursor-request>
fn Request(&self) -> DomRoot<IDBRequest> {
self.request
.get()
.expect("IDBCursor.request should be set when cursor is opened")
}
}

View file

@ -0,0 +1,78 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use js::rust::MutableHandleValue;
use net_traits::indexeddb_thread::IndexedDBKeyRange;
use crate::dom::bindings::codegen::Bindings::IDBCursorBinding::IDBCursorDirection;
use crate::dom::bindings::codegen::Bindings::IDBCursorWithValueBinding::IDBCursorWithValueMethods;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::idbcursor::{IDBCursor, ObjectStoreOrIndex};
use crate::dom::idbtransaction::IDBTransaction;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
#[dom_struct]
pub(crate) struct IDBCursorWithValue {
cursor: IDBCursor,
}
impl IDBCursorWithValue {
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
fn new_inherited(
transaction: &IDBTransaction,
direction: IDBCursorDirection,
got_value: bool,
source: ObjectStoreOrIndex,
range: IndexedDBKeyRange,
key_only: bool,
) -> IDBCursorWithValue {
IDBCursorWithValue {
cursor: IDBCursor::new_inherited(
transaction,
direction,
got_value,
source,
range,
key_only,
),
}
}
#[expect(unused)]
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
global: &GlobalScope,
transaction: &IDBTransaction,
direction: IDBCursorDirection,
got_value: bool,
source: ObjectStoreOrIndex,
range: IndexedDBKeyRange,
key_only: bool,
can_gc: CanGc,
) -> DomRoot<IDBCursorWithValue> {
reflect_dom_object(
Box::new(IDBCursorWithValue::new_inherited(
transaction,
direction,
got_value,
source,
range,
key_only,
)),
global,
can_gc,
)
}
}
impl IDBCursorWithValueMethods<crate::DomTypeHolder> for IDBCursorWithValue {
/// <https://www.w3.org/TR/IndexedDB-2/#dom-idbcursorwithvalue-value>
fn Value(&self, _cx: SafeJSContext, value: MutableHandleValue) {
self.cursor.value(value);
}
}

View file

@ -407,6 +407,8 @@ pub(crate) mod htmltrackelement;
pub(crate) mod htmlulistelement;
pub(crate) mod htmlunknownelement;
pub(crate) mod htmlvideoelement;
pub(crate) mod idbcursor;
pub(crate) mod idbcursorwithvalue;
pub(crate) mod idbdatabase;
pub(crate) mod idbfactory;
pub(crate) mod idbindex;

View file

@ -0,0 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://w3c.github.io/IndexedDB/#idbcursor
*
*/
// https://w3c.github.io/IndexedDB/#idbcursor
[Pref="dom_indexeddb_enabled", Exposed=(Window,Worker)]
interface IDBCursor {
readonly attribute (IDBObjectStore or IDBIndex) source;
readonly attribute IDBCursorDirection direction;
readonly attribute any key;
readonly attribute any primaryKey;
[SameObject] readonly attribute IDBRequest request;
// undefined advance([EnforceRange] unsigned long count);
// undefined continue(optional any key);
// undefined continuePrimaryKey(any key, any primaryKey);
// [NewObject] IDBRequest update(any value);
// [NewObject] IDBRequest delete();
};
enum IDBCursorDirection {
"next",
"nextunique",
"prev",
"prevunique"
};

View file

@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://w3c.github.io/IndexedDB/#idbcursorwithvalue
*
*/
// https://w3c.github.io/IndexedDB/#idbcursorwithvalue
[Pref="dom_indexeddb_enabled", Exposed=(Window,Worker)]
interface IDBCursorWithValue : IDBCursor {
readonly attribute any value;
};

View file

@ -2,32 +2,8 @@
expected: ERROR
[historical.any.html]
["NEXT" should not be supported on IDBCursor.]
expected: FAIL
["NEXT_NO_DUPLICATE" should not be supported on IDBCursor.]
expected: FAIL
["PREV" should not be supported on IDBCursor.]
expected: FAIL
["PREV_NO_DUPLICATE" should not be supported on IDBCursor.]
expected: FAIL
[historical.any.worker.html]
["NEXT" should not be supported on IDBCursor.]
expected: FAIL
["NEXT_NO_DUPLICATE" should not be supported on IDBCursor.]
expected: FAIL
["PREV" should not be supported on IDBCursor.]
expected: FAIL
["PREV_NO_DUPLICATE" should not be supported on IDBCursor.]
expected: FAIL
[historical.any.sharedworker.html]
expected: ERROR

View file

@ -59,39 +59,6 @@
[IDBIndex interface: operation openKeyCursor(optional any, optional IDBCursorDirection)]
expected: FAIL
[IDBCursor interface: existence and properties of interface object]
expected: FAIL
[IDBCursor interface object length]
expected: FAIL
[IDBCursor interface object name]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[IDBCursor interface: attribute source]
expected: FAIL
[IDBCursor interface: attribute direction]
expected: FAIL
[IDBCursor interface: attribute key]
expected: FAIL
[IDBCursor interface: attribute primaryKey]
expected: FAIL
[IDBCursor interface: attribute request]
expected: FAIL
[IDBCursor interface: operation advance(unsigned long)]
expected: FAIL
@ -107,27 +74,6 @@
[IDBCursor interface: operation delete()]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface object]
expected: FAIL
[IDBCursorWithValue interface object length]
expected: FAIL
[IDBCursorWithValue interface object name]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[IDBCursorWithValue interface: attribute value]
expected: FAIL
[IDBTransaction interface: attribute durability]
expected: FAIL
@ -229,39 +175,6 @@
[IDBIndex interface: operation openKeyCursor(optional any, optional IDBCursorDirection)]
expected: FAIL
[IDBCursor interface: existence and properties of interface object]
expected: FAIL
[IDBCursor interface object length]
expected: FAIL
[IDBCursor interface object name]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[IDBCursor interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[IDBCursor interface: attribute source]
expected: FAIL
[IDBCursor interface: attribute direction]
expected: FAIL
[IDBCursor interface: attribute key]
expected: FAIL
[IDBCursor interface: attribute primaryKey]
expected: FAIL
[IDBCursor interface: attribute request]
expected: FAIL
[IDBCursor interface: operation advance(unsigned long)]
expected: FAIL
@ -277,27 +190,6 @@
[IDBCursor interface: operation delete()]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface object]
expected: FAIL
[IDBCursorWithValue interface object length]
expected: FAIL
[IDBCursorWithValue interface object name]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[IDBCursorWithValue interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[IDBCursorWithValue interface: attribute value]
expected: FAIL
[IDBTransaction interface: attribute durability]
expected: FAIL

View file

@ -4,9 +4,3 @@
[The CanvasPath interface object should be exposed.]
expected: FAIL
[The IDBCursor interface object should be exposed.]
expected: FAIL
[The IDBCursorWithValue interface object should be exposed.]
expected: FAIL