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}