script/dom/indexeddb/
idbkeyrange.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::gc::MutableHandleValue;
8use js::rust::HandleValue;
9use script_bindings::codegen::GenericBindings::IDBKeyRangeBinding::IDBKeyRangeMethods;
10use script_bindings::root::DomRoot;
11use script_bindings::script_runtime::CanGc;
12use storage_traits::indexeddb::IndexedDBKeyRange;
13
14use crate::dom::bindings::error::{Error, Fallible};
15use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
16use crate::dom::globalscope::GlobalScope;
17use crate::indexeddb::{convert_value_to_key, key_type_to_jsval};
18
19#[dom_struct]
20pub struct IDBKeyRange {
21    reflector_: Reflector,
22    #[no_trace]
23    inner: IndexedDBKeyRange,
24}
25
26impl IDBKeyRange {
27    pub fn new_inherited(inner: IndexedDBKeyRange) -> Self {
28        IDBKeyRange {
29            reflector_: Reflector::new(),
30            inner,
31        }
32    }
33
34    pub fn new(global: &GlobalScope, inner: IndexedDBKeyRange, can_gc: CanGc) -> DomRoot<Self> {
35        reflect_dom_object(Box::new(IDBKeyRange::new_inherited(inner)), global, can_gc)
36    }
37
38    pub fn inner(&self) -> &IndexedDBKeyRange {
39        &self.inner
40    }
41}
42
43impl IDBKeyRangeMethods<crate::DomTypeHolder> for IDBKeyRange {
44    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-lower>
45    fn Lower(&self, cx: &mut JSContext, answer: MutableHandleValue) {
46        if let Some(lower) = self.inner.lower.as_ref() {
47            key_type_to_jsval(cx, lower, answer);
48        }
49    }
50
51    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upper>
52    fn Upper(&self, cx: &mut JSContext, answer: MutableHandleValue) {
53        if let Some(upper) = self.inner.upper.as_ref() {
54            key_type_to_jsval(cx, upper, answer);
55        }
56    }
57
58    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-loweropen>
59    fn LowerOpen(&self) -> bool {
60        self.inner.lower_open
61    }
62
63    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upperopen>
64    fn UpperOpen(&self) -> bool {
65        self.inner.upper_open
66    }
67
68    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-only>
69    fn Only(
70        cx: &mut JSContext,
71        global: &GlobalScope,
72        value: HandleValue,
73    ) -> Fallible<DomRoot<IDBKeyRange>> {
74        // Step 1. Let key be the result of converting a value to a key with value. Rethrow any
75        // exceptions.
76        // Step 2. If key is "invalid value" or "invalid type", throw a "DataError"
77        // DOMException.
78        let key = convert_value_to_key(cx, value, None)?.into_result()?;
79
80        // Step 3. Create and return a new key range containing only key.
81        let inner = IndexedDBKeyRange::only(key);
82        Ok(IDBKeyRange::new(global, inner, CanGc::from_cx(cx)))
83    }
84
85    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-lowerbound>
86    fn LowerBound(
87        cx: &mut JSContext,
88        global: &GlobalScope,
89        lower: HandleValue,
90        open: bool,
91    ) -> Fallible<DomRoot<IDBKeyRange>> {
92        // Step 1. Let lowerKey be the result of converting a value to a key with lower. Rethrow
93        // any exceptions.
94        // Step 2. If lowerKey is invalid, throw a "DataError" DOMException.
95        let lower_key = convert_value_to_key(cx, lower, None)?.into_result()?;
96
97        // Step 3. Create and return a new key range with lower bound set to lowerKey, lower open
98        // flag set to open, upper bound set to null, and upper open flag set to true.
99        let inner = IndexedDBKeyRange::lower_bound(lower_key, open);
100        Ok(IDBKeyRange::new(global, inner, CanGc::from_cx(cx)))
101    }
102
103    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upperbound>
104    fn UpperBound(
105        cx: &mut JSContext,
106        global: &GlobalScope,
107        upper: HandleValue,
108        open: bool,
109    ) -> Fallible<DomRoot<IDBKeyRange>> {
110        // Step 1. Let upperKey be the result of converting a value to a key with upper. Rethrow
111        // any exceptions.
112        // Step 2. If upperKey is "invalid value" or "invalid type", throw a "DataError"
113        // DOMException.
114        let upper_key = convert_value_to_key(cx, upper, None)?.into_result()?;
115
116        // Step 3. Create and return a new key range with lower bound set to null, lower open flag
117        // set to true, upper bound set to upperKey, and upper open flag set to open.
118        let inner = IndexedDBKeyRange::upper_bound(upper_key, open);
119        Ok(IDBKeyRange::new(global, inner, CanGc::from_cx(cx)))
120    }
121
122    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-bound>
123    fn Bound(
124        cx: &mut JSContext,
125        global: &GlobalScope,
126        lower: HandleValue,
127        upper: HandleValue,
128        lower_open: bool,
129        upper_open: bool,
130    ) -> Fallible<DomRoot<IDBKeyRange>> {
131        // Step 1. Let lowerKey be the result of converting a value to a key with lower. Rethrow
132        // any exceptions.
133        // Step 2. If lowerKey is "invalid value" or "invalid type", throw a "DataError"
134        // DOMException.
135        let lower_key = convert_value_to_key(cx, lower, None)?.into_result()?;
136
137        // Step 3. Let upperKey be the result of converting a value to a key with upper. Rethrow
138        // any exceptions.
139        // Step 4. If upperKey is "invalid value" or "invalid type", throw a "DataError"
140        // DOMException.
141        let upper_key = convert_value_to_key(cx, upper, None)?.into_result()?;
142
143        // Step 5. If lowerKey is greater than upperKey, throw a "DataError" DOMException.
144        if lower_key > upper_key {
145            return Err(Error::Data(None));
146        }
147
148        // Step 6. Create and return a new key range with lower bound set to lowerKey, lower open
149        // flag set to lowerOpen, upper bound set to upperKey and upper open flag set to upperOpen.
150        let inner =
151            IndexedDBKeyRange::new(Some(lower_key), Some(upper_key), lower_open, upper_open);
152        Ok(IDBKeyRange::new(global, inner, CanGc::from_cx(cx)))
153    }
154
155    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-_includes>
156    fn Includes(&self, cx: &mut JSContext, key: HandleValue) -> Fallible<bool> {
157        // Step 1. Let k be the result of converting a value to a key with key. Rethrow any
158        // exceptions.
159        // Step 2. If k is "invalid value" or "invalid type", throw a "DataError" DOMException.
160        let k = convert_value_to_key(cx, key, None)?.into_result()?;
161
162        // Step 3. Return true if k is in this range, and false otherwise.
163        Ok(self.inner.contains(&k))
164    }
165}