script_bindings/
error.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 std::ffi::CString;
6
7use js::error::throw_type_error;
8use js::jsapi::JS_IsExceptionPending;
9
10use crate::codegen::PrototypeList::proto_id_to_name;
11use crate::num::Finite;
12use crate::script_runtime::JSContext as SafeJSContext;
13
14/// DOM exceptions that can be thrown by a native DOM method.
15/// <https://webidl.spec.whatwg.org/#dfn-error-names-table>
16#[derive(Clone, Debug, MallocSizeOf)]
17pub enum Error {
18    /// IndexSizeError DOMException
19    IndexSize(Option<String>),
20    /// NotFoundError DOMException
21    NotFound(Option<String>),
22    /// HierarchyRequestError DOMException
23    HierarchyRequest(Option<String>),
24    /// WrongDocumentError DOMException
25    WrongDocument(Option<String>),
26    /// InvalidCharacterError DOMException
27    InvalidCharacter(Option<String>),
28    /// NotSupportedError DOMException
29    NotSupported(Option<String>),
30    /// InUseAttributeError DOMException
31    InUseAttribute(Option<String>),
32    /// InvalidStateError DOMException
33    InvalidState(Option<String>),
34    /// SyntaxError DOMException
35    Syntax(Option<String>),
36    /// NamespaceError DOMException
37    Namespace(Option<String>),
38    /// InvalidAccessError DOMException
39    InvalidAccess(Option<String>),
40    /// SecurityError DOMException
41    Security(Option<String>),
42    /// NetworkError DOMException
43    Network(Option<String>),
44    /// AbortError DOMException
45    Abort(Option<String>),
46    /// TimeoutError DOMException
47    Timeout(Option<String>),
48    /// InvalidNodeTypeError DOMException
49    InvalidNodeType(Option<String>),
50    /// DataCloneError DOMException
51    DataClone(Option<String>),
52    /// TransactionInactiveError DOMException
53    TransactionInactive(Option<String>),
54    /// ReadOnlyError DOMException
55    ReadOnly(Option<String>),
56    /// VersionError DOMException
57    Version(Option<String>),
58    /// NoModificationAllowedError DOMException
59    NoModificationAllowed(Option<String>),
60    /// QuotaExceededError DOMException
61    QuotaExceeded {
62        quota: Option<Finite<f64>>,
63        requested: Option<Finite<f64>>,
64    },
65    /// TypeMismatchError DOMException
66    TypeMismatch(Option<String>),
67    /// InvalidModificationError DOMException
68    InvalidModification(Option<String>),
69    /// NotReadableError DOMException
70    NotReadable(Option<String>),
71    /// DataError DOMException
72    Data(Option<String>),
73    /// OperationError DOMException
74    Operation(Option<String>),
75    /// NotAllowedError DOMException
76    NotAllowed(Option<String>),
77    /// EncodingError DOMException
78    Encoding(Option<String>),
79    /// ConstraintError DOMException
80    Constraint(Option<String>),
81
82    /// TypeError JavaScript Error
83    Type(CString),
84    /// RangeError JavaScript Error
85    Range(CString),
86
87    /// A JavaScript exception is already pending.
88    JSFailed,
89}
90
91/// The return type for IDL operations that can throw DOM exceptions.
92pub type Fallible<T> = Result<T, Error>;
93
94/// The return type for IDL operations that can throw DOM exceptions and
95/// return `()`.
96pub type ErrorResult = Fallible<()>;
97
98/// Throw an exception to signal that a `JSObject` can not be converted to a
99/// given DOM type.
100pub fn throw_invalid_this(cx: SafeJSContext, proto_id: u16) {
101    debug_assert!(unsafe { !JS_IsExceptionPending(*cx) });
102    let mut vec = "\"this\" object does not implement interface "
103        .as_bytes()
104        .to_vec();
105    vec.extend_from_slice(proto_id_to_name(proto_id).as_bytes());
106    let error = CString::new(vec).expect("WebIDL name should not contain nul byte");
107    unsafe { throw_type_error(*cx, &error) };
108}
109
110pub fn throw_constructor_without_new(cx: SafeJSContext, name: &str) {
111    debug_assert!(unsafe { !JS_IsExceptionPending(*cx) });
112    let mut error = name.as_bytes().to_vec();
113    error.extend_from_slice(b" constructor: 'new' is required");
114    let error = CString::new(error).expect("WebIDL name should not contain nul byte");
115    unsafe { throw_type_error(*cx, &error) };
116}
117
118#[macro_export]
119/// Creates a `CString` using interpolation of runtime expressions.
120/// Basically a `format!` that produces a `CString`.
121///
122/// Because data can come from untrusted sources, it will check the interior for
123/// null bytes and replace them with `\u0000`.
124macro_rules! cformat {
125    ($($arg:tt)*) => {
126        {
127            use std::io::Write;
128            let mut s = Vec::new();
129            write!(&mut s, $($arg)*).unwrap();
130            std::ffi::CString::new(s).or_else(|s| {
131                let s = s.into_vec();
132                let mut out = Vec::with_capacity(s.len());
133                for b in s {
134                    if b == 0 {
135                        out.extend_from_slice(b"\\u0000");
136                    } else {
137                        out.push(b);
138                    }
139                }
140                std::ffi::CString::new(out)
141            }).expect("nul bytes should be replaced")
142        }
143    }
144}