script: Add message to SyntaxError (#39056)

Adding an optional message to be attached to a SyntaxError. Unblocks
#39050.

The enum definition of Syntax is now `Syntax(Option<String>)`. Future
PRs should probably add more appropriate messages to some of the
`Syntax(None)`s.

Testing: Just a refactor
Fixes: Partially #39053

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
This commit is contained in:
Ashwin Naren 2025-09-01 22:51:36 -07:00 committed by GitHub
parent d01bba4e50
commit 97c8c83cbb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 82 additions and 70 deletions

View file

@ -1309,7 +1309,7 @@ impl CanvasState {
can_gc,
)))
} else {
Err(Error::Syntax)
Err(Error::Syntax(None))
}
}

View file

@ -108,7 +108,15 @@ pub(crate) fn create_dom_exception(
Error::NotSupported => DOMErrorName::NotSupportedError,
Error::InUseAttribute => DOMErrorName::InUseAttributeError,
Error::InvalidState => DOMErrorName::InvalidStateError,
Error::Syntax => DOMErrorName::SyntaxError,
Error::Syntax(Some(custom_message)) => {
return Ok(DOMException::new_with_custom_message(
global,
DOMErrorName::SyntaxError,
custom_message,
can_gc,
));
},
Error::Syntax(None) => DOMErrorName::SyntaxError,
Error::Namespace => DOMErrorName::NamespaceError,
Error::InvalidAccess => DOMErrorName::InvalidAccessError,
Error::Security => DOMErrorName::SecurityError,

View file

@ -64,7 +64,7 @@ impl CanvasGradientMethods<crate::DomTypeHolder> for CanvasGradient {
let color = match parse_color(None, &color) {
Ok(color) => color,
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
self.stops.borrow_mut().push(CanvasGradientStop {

View file

@ -105,7 +105,9 @@ impl CSSMethods<crate::DomTypeHolder> for CSS {
RegisterPropertyError::InvalidSyntax |
RegisterPropertyError::InvalidInitialValue |
RegisterPropertyError::NoInitialValue |
RegisterPropertyError::InitialValueNotComputationallyIndependent => Error::Syntax,
RegisterPropertyError::InitialValueNotComputationallyIndependent => {
Error::Syntax(None)
},
RegisterPropertyError::AlreadyRegistered => Error::InvalidModification,
})?;

View file

@ -35,7 +35,7 @@ unsafe_no_jsmanaged_fields!(RulesSource);
impl Convert<Error> for RulesMutateError {
fn convert(self) -> Error {
match self {
RulesMutateError::Syntax => Error::Syntax,
RulesMutateError::Syntax => Error::Syntax(None),
RulesMutateError::IndexSize => Error::IndexSize,
RulesMutateError::HierarchyRequest => Error::HierarchyRequest,
RulesMutateError::InvalidState => Error::InvalidState,

View file

@ -360,7 +360,7 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
// Step 2. If name is not a valid custom element name, then throw a "SyntaxError" DOMException.
if !is_valid_custom_element_name(&name) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 3. If this's custom element definition set contains an item with name name,

View file

@ -236,7 +236,7 @@ impl DissimilarOriginWindow {
"/" => Some(source_origin.clone()),
url => match ServoUrl::parse(url) {
Ok(url) => Some(url.origin().clone()),
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
},
};
let msg = ScriptToConstellationMessage::PostMessage {

View file

@ -1196,12 +1196,12 @@ pub(crate) fn transform_to_matrix(value: String) -> Fallible<(bool, Transform3D<
let transform = match parser.parse_entirely(|t| transform::parse(&context, t)) {
Ok(result) => result,
Err(..) => return Err(error::Error::Syntax),
Err(..) => return Err(error::Error::Syntax(None)),
};
let (m, is_3d) = match transform.to_transform_3d_matrix_f64(None) {
Ok(result) => result,
Err(..) => return Err(error::Error::Syntax),
Err(..) => return Err(error::Error::Syntax(None)),
};
Ok((!is_3d, m))

View file

@ -64,7 +64,7 @@ impl DOMTokenList {
fn check_token_exceptions(&self, token: &str) -> Fallible<Atom> {
match token {
"" => Err(Error::Syntax),
"" => Err(Error::Syntax(None)),
slice if slice.find(HTML_SPACE_CHARACTERS).is_some() => Err(Error::InvalidCharacter),
slice => Ok(Atom::from(slice)),
}
@ -190,7 +190,7 @@ impl DOMTokenListMethods<crate::DomTypeHolder> for DOMTokenList {
fn Replace(&self, token: DOMString, new_token: DOMString, can_gc: CanGc) -> Fallible<bool> {
if token.is_empty() || new_token.is_empty() {
// Step 1.
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
if token.contains(HTML_SPACE_CHARACTERS) || new_token.contains(HTML_SPACE_CHARACTERS) {
// Step 2.

View file

@ -270,7 +270,7 @@ impl FromStr for AdjacentPosition {
"afterbegin" => Ok(AdjacentPosition::AfterBegin),
"beforeend" => Ok(AdjacentPosition::BeforeEnd),
"afterend" => Ok(AdjacentPosition::AfterEnd),
_ => Err(Error::Syntax)
_ => Err(Error::Syntax(None))
}
}
}
@ -4068,7 +4068,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
&selectors,
&UrlExtraData(url.get_arc()),
) {
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
Ok(selectors) => selectors,
};
@ -4095,7 +4095,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
&selectors,
&UrlExtraData(url.get_arc()),
) {
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
Ok(selectors) => selectors,
};

View file

@ -570,7 +570,7 @@ impl EventSourceMethods<crate::DomTypeHolder> for EventSource {
let url_record = match base_url.join(&url) {
Ok(u) => u,
// Step 4 If urlRecord is failure, then throw a "SyntaxError" DOMException.
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
// Step 1 Let ev be a new EventSource object.
let ev = EventSource::new(

View file

@ -150,7 +150,7 @@ fn parse_font_face_descriptors(
if error_reporter.not_encountered_error.get() {
Ok(parsed_font_face_rule)
} else {
Err(Error::Syntax)
Err(Error::Syntax(None))
}
}
@ -191,7 +191,7 @@ impl FontFace {
let font_status_promise = Promise::new(global, can_gc);
// If any of them fail to parse correctly, reject font faces [[FontStatusPromise]] with a
// DOMException named "SyntaxError"
font_status_promise.reject_error(Error::Syntax, can_gc);
font_status_promise.reject_error(Error::Syntax(None), can_gc);
// set font faces corresponding attributes to the empty string, and set font faces status
// attribute to "error"

View file

@ -757,7 +757,7 @@ impl HTMLElement {
.nth(1)
.is_some_and(|ch| ch.is_ascii_lowercase())
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
self.as_element()
.set_custom_attribute(to_snake_case(name), value, can_gc)

View file

@ -212,7 +212,7 @@ impl IDBDatabaseMethods<crate::DomTypeHolder> for IDBDatabase {
// Step 5
if let Some(path) = key_path {
if !is_valid_key_path(path) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
}

View file

@ -138,7 +138,7 @@ impl IntersectionObserver {
let root_margin = if let Ok(margin) = parse_a_margin(init.rootMargin.as_ref()) {
margin
} else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
// Step 4.
@ -147,7 +147,7 @@ impl IntersectionObserver {
let scroll_margin = if let Ok(margin) = parse_a_margin(init.scrollMargin.as_ref()) {
margin
} else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
// Step 1 and step 2, 3, 4 setter

View file

@ -274,7 +274,7 @@ impl LocationMethods<crate::DomTypeHolder> for Location {
let base_url = self.entry_settings_object().api_base_url();
let url = match base_url.join(&url.0) {
Ok(url) => url,
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
Ok(Some(url))
@ -304,7 +304,7 @@ impl LocationMethods<crate::DomTypeHolder> for Location {
let base_url = self.entry_settings_object().api_base_url();
let url = match base_url.join(&url.0) {
Ok(url) => url,
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
// Step 3: Location-object navigate to the resulting URL record with
// the replacement flag set.
@ -504,7 +504,7 @@ impl LocationMethods<crate::DomTypeHolder> for Location {
if copy_url.as_mut_url().set_scheme(scheme).is_err() {
// Step 5: If possibleFailure is failure, then throw a "SyntaxError" DOMException.
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 6: If copyURL's scheme is not an HTTP(S) scheme, then terminate these steps.

View file

@ -1131,7 +1131,7 @@ impl Node {
&UrlExtraData(doc.url().get_arc()),
) {
// Step 2.
Err(_) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax(None)),
// Step 3.
Ok(selectors) => {
let mut nth_index_cache = Default::default();
@ -1168,7 +1168,7 @@ impl Node {
&UrlExtraData(url.get_arc()),
) {
// Step 2.
Err(_) => Err(Error::Syntax),
Err(_) => Err(Error::Syntax(None)),
// Step 3.
Ok(selectors) => {
let mut descendants = self.traverse_preorder(ShadowIncluding::No);

View file

@ -490,7 +490,7 @@ impl PerformanceMethods<crate::DomTypeHolder> for Performance {
let global = self.global();
// Step 1.
if global.is::<Window>() && INVALID_ENTRY_NAMES.contains(&mark_name.as_ref()) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Steps 2 to 6.

View file

@ -160,12 +160,12 @@ impl PerformanceObserverMethods<crate::DomTypeHolder> for PerformanceObserver {
// Step 3
if options.entryTypes.is_none() && options.type_.is_none() {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 4
if options.entryTypes.is_some() && (options.buffered.is_some() || options.type_.is_some()) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// If this point is reached, then one of options.entryTypes or options.type_

View file

@ -647,7 +647,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 17. If the [[type]] internal slot of result is "secret" or "private" and usages
// is empty, then throw a SyntaxError.
if matches!(result.Type(), KeyType::Secret | KeyType::Private) && result.usages().is_empty() {
promise.reject_error(Error::Syntax, CanGc::note());
promise.reject_error(Error::Syntax(None), CanGc::note());
return;
}
@ -759,7 +759,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let data_string = match json_web_key.k {
Some(s) => s.to_string(),
None => {
promise.reject_error(Error::Syntax, can_gc);
promise.reject_error(Error::Syntax(None), can_gc);
return promise;
},
};
@ -769,7 +769,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
{
Ok(data) => data,
Err(_) => {
promise.reject_error(Error::Syntax, can_gc);
promise.reject_error(Error::Syntax(None), can_gc);
return promise;
},
}
@ -919,19 +919,19 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// TODO: Support more than just a subset of the JWK dict, or find a way to
// stringify via SM internals
let Some(k) = key.k else {
promise.reject_error(Error::Syntax, CanGc::note());
promise.reject_error(Error::Syntax(None), CanGc::note());
return;
};
let Some(alg) = key.alg else {
promise.reject_error(Error::Syntax, CanGc::note());
promise.reject_error(Error::Syntax(None), CanGc::note());
return;
};
let Some(ext) = key.ext else {
promise.reject_error(Error::Syntax, CanGc::note());
promise.reject_error(Error::Syntax(None), CanGc::note());
return;
};
let Some(key_ops) = key.key_ops else {
promise.reject_error(Error::Syntax, CanGc::note());
promise.reject_error(Error::Syntax(None), CanGc::note());
return;
};
let key_ops_str = key_ops.iter().map(|op| op.to_string()).collect::<Vec<String>>();
@ -1405,7 +1405,7 @@ macro_rules! value_from_js_object {
($t: ty, $cx: ident, $value: ident) => {{
let params_result = <$t>::new($cx, $value.handle()).map_err(|_| Error::JSFailed)?;
let ConversionResult::Success(params) = params_result else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
params
}};
@ -1639,21 +1639,21 @@ fn normalize_algorithm_for_key_wrap(
ALG_AES_KW => KeyWrapAlgorithm::AesKw,
ALG_AES_CBC => {
let AlgorithmIdentifier::Object(obj) = algorithm else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
rooted!(in(*cx) let value = ObjectValue(obj.get()));
KeyWrapAlgorithm::AesCbc(value_from_js_object!(AesCbcParams, cx, value).into())
},
ALG_AES_CTR => {
let AlgorithmIdentifier::Object(obj) = algorithm else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
rooted!(in(*cx) let value = ObjectValue(obj.get()));
KeyWrapAlgorithm::AesCtr(value_from_js_object!(AesCtrParams, cx, value).into())
},
ALG_AES_GCM => {
let AlgorithmIdentifier::Object(obj) = algorithm else {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
};
rooted!(in(*cx) let value = ObjectValue(obj.get()));
KeyWrapAlgorithm::AesGcm(value_from_js_object!(AesGcmParams, cx, value).into())
@ -2066,7 +2066,7 @@ impl SubtleCrypto {
)
}) || usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
},
ALG_AES_KW => {
@ -2075,7 +2075,7 @@ impl SubtleCrypto {
.any(|usage| !matches!(usage, KeyUsage::WrapKey | KeyUsage::UnwrapKey)) ||
usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
},
_ => return Err(Error::NotSupported),
@ -2128,7 +2128,7 @@ impl SubtleCrypto {
.iter()
.any(|usage| !matches!(usage, KeyUsage::Sign | KeyUsage::Verify))
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 2.
@ -2213,7 +2213,7 @@ impl SubtleCrypto {
)
}) || usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
if !matches!(format, KeyFormat::Raw | KeyFormat::Jwk) {
return Err(Error::NotSupported);
@ -2326,12 +2326,12 @@ impl SubtleCrypto {
.any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 2. If extractable is not false, then throw a SyntaxError.
if extractable {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 3. Let key be a new CryptoKey representing the key data provided in keyData.
@ -2383,7 +2383,7 @@ impl SubtleCrypto {
.any(|usage| !matches!(usage, KeyUsage::Sign | KeyUsage::Verify)) ||
usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 3. Let hash be a new KeyAlgorithm.
@ -2592,12 +2592,12 @@ impl SubtleCrypto {
.any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
usages.is_empty()
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 3. If extractable is not false, then throw a SyntaxError.
if extractable {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 4. Let key be a new CryptoKey representing keyData.

View file

@ -369,7 +369,7 @@ impl RTCDataChannelMethods<crate::DomTypeHolder> for RTCDataChannel {
// https://www.w3.org/TR/webrtc/#dom-datachannel-binarytype
fn SetBinaryType(&self, value: DOMString) -> Fallible<()> {
if value != "blob" || value != "arraybuffer" {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
*self.binary_type.borrow_mut() = value;
Ok(())

View file

@ -190,7 +190,7 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
// Step 1. Let baseURL be this's relevant settings object's API base URL.
// Step 2. Let urlRecord be the result of applying the URL parser to url with baseURL.
// Step 3. If urlRecord is failure, then throw a "SyntaxError" DOMException.
let mut url_record = ServoUrl::parse(&url).or(Err(Error::Syntax))?;
let mut url_record = ServoUrl::parse(&url).or(Err(Error::Syntax(None)))?;
// Step 4. If urlRecords scheme is "http", then set urlRecords scheme to "ws".
// Step 5. Otherwise, if urlRecords scheme is "https", set urlRecords scheme to "wss".
@ -209,12 +209,12 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
.expect("Can't set scheme from https to wss");
},
"ws" | "wss" => {},
_ => return Err(Error::Syntax),
_ => return Err(Error::Syntax(None)),
}
// Step 7. If urlRecords fragment is non-null, then throw a "SyntaxError" DOMException.
if url_record.fragment().is_some() {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 8. If protocols is a string, set protocols to a sequence consisting of just that string.
@ -236,12 +236,12 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
.iter()
.any(|p| p.eq_ignore_ascii_case(protocol))
{
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// https://tools.ietf.org/html/rfc6455#section-4.1
if !is_token(protocol.as_bytes()) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
}
@ -429,7 +429,7 @@ impl WebSocketMethods<crate::DomTypeHolder> for WebSocket {
if let Some(ref reason) = reason {
if reason.0.len() > 123 {
// reason cannot be larger than 123 bytes
return Err(Error::Syntax);
return Err(Error::Syntax(Some("Reason too long".to_string())));
}
}

View file

@ -2009,7 +2009,7 @@ impl Window {
"/" => Some(source_origin.clone()),
url => match ServoUrl::parse(url) {
Ok(url) => Some(url.origin().clone()),
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
},
};

View file

@ -536,7 +536,7 @@ impl WindowProxy {
.unwrap();
let url = match existing_document.url().join(&url) {
Ok(url) => url,
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
let referrer = if noreferrer {
Referrer::NoReferrer

View file

@ -179,7 +179,7 @@ impl WorkerMethods<crate::DomTypeHolder> for Worker {
// Step 2-4.
let worker_url = match global.api_base_url().join(&compliant_script_url) {
Ok(url) => url,
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
let (sender, receiver) = unbounded();

View file

@ -392,7 +392,7 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
let url = self.worker_url.borrow().join(&url);
match url {
Ok(url) => urls.push(url),
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
}

View file

@ -143,7 +143,7 @@ impl WorkletMethods<crate::DomTypeHolder> for Worklet {
Err(err) => {
// Step 4.
debug!("URL {:?} parse error {:?}.", module_url.0, err);
promise.reject_error(Error::Syntax, can_gc);
promise.reject_error(Error::Syntax(None), can_gc);
return promise;
},
};

View file

@ -366,7 +366,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
Some(parsed_method) => {
// Step 3
if !is_token(&method) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
// Step 2
@ -375,7 +375,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
let mut parsed_url = match base.join(&url.0) {
Ok(parsed) => parsed,
// Step 7
Err(_) => return Err(Error::Syntax),
Err(_) => return Err(Error::Syntax(None)),
};
// Step 9
@ -424,7 +424,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
// Step 3
// This includes cases where as_str() returns None, and when is_token() returns false,
// both of which indicate invalid extension method names
_ => Err(Error::Syntax),
_ => Err(Error::Syntax(None)),
}
}
@ -442,10 +442,10 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
// Step 4: If name is not a header name or value is not a header value, then throw a
// "SyntaxError" DOMException.
if !is_token(&name) || !is_field_value(value) {
return Err(Error::Syntax);
return Err(Error::Syntax(None));
}
let name_str = name.as_str().ok_or(Error::Syntax)?;
let name_str = name.as_str().ok_or(Error::Syntax(None))?;
// Step 5: If (name, value) is a forbidden request-header, then return.
if is_forbidden_request_header(name_str, value) {
@ -885,7 +885,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
Ok(mime) => mime,
Err(_) => "application/octet-stream"
.parse::<Mime>()
.map_err(|_| Error::Syntax)?,
.map_err(|_| Error::Syntax(None))?,
};
*self.override_mime_type.borrow_mut() = Some(override_mime);

View file

@ -70,7 +70,8 @@ impl XPathEvaluatorMethods<crate::DomTypeHolder> for XPathEvaluator {
let window = global.as_window();
// NB: this function is *not* Fallible according to the spec, so we swallow any parsing errors and
// just pass a None as the expression... it's not great.
let parsed_expression = crate::xpath::parse(&expression).map_err(|_e| Error::Syntax)?;
let parsed_expression =
crate::xpath::parse(&expression).map_err(|_e| Error::Syntax(None))?;
Ok(XPathExpression::new(
window,
None,
@ -97,7 +98,8 @@ impl XPathEvaluatorMethods<crate::DomTypeHolder> for XPathEvaluator {
) -> Fallible<DomRoot<XPathResult>> {
let global = self.global();
let window = global.as_window();
let parsed_expression = crate::xpath::parse(&expression_str).map_err(|_| Error::Syntax)?;
let parsed_expression =
crate::xpath::parse(&expression_str).map_err(|_| Error::Syntax(None))?;
let expression = XPathExpression::new(window, None, can_gc, parsed_expression);
XPathExpressionMethods::<crate::DomTypeHolder>::Evaluate(
&*expression,

View file

@ -30,7 +30,7 @@ pub enum Error {
/// InvalidStateError DOMException
InvalidState,
/// SyntaxError DOMException
Syntax,
Syntax(Option<String>),
/// NamespaceError DOMException
Namespace,
/// InvalidAccessError DOMException