mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
Continuation of https://github.com/servo/servo/pull/42135, switch Error::Type and Error::Range to also use CStrings internally, as they are converted to CString for throwing JS exceptions (other get thrown as DomException object, which uses rust string internally). Changes in script crate are mechanical. Testing: Should be covered by WPT tests. Part of #42126 Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
145 lines
4.9 KiB
Rust
145 lines
4.9 KiB
Rust
/* 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")
|
|
}
|
|
}
|
|
}
|