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