Skip to content

Commit 798945e

Browse files
committed
Add DomExceptionName
1 parent 0b5172e commit 798945e

File tree

2 files changed

+135
-46
lines changed

2 files changed

+135
-46
lines changed

modules/llrt_abort/src/abort_signal.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::sync::{Arc, RwLock};
44

55
use llrt_events::{Emitter, EventEmitter, EventList};
6-
use llrt_exceptions::DOMException;
6+
use llrt_exceptions::{DOMException, DOMExceptionName};
77
use llrt_utils::mc_oneshot;
88
use rquickjs::{
99
class::{Trace, Tracer},
@@ -160,7 +160,11 @@ impl<'js> AbortSignal<'js> {
160160
pub fn send_aborted(this: This<Class<'js, Self>>, ctx: Ctx<'js>) -> Result<()> {
161161
let mut borrow = this.borrow_mut();
162162
borrow.aborted = true;
163-
let reason = get_reason_or_dom_exception(&ctx, borrow.reason.as_ref(), "AbortError")?;
163+
let reason = get_reason_or_dom_exception(
164+
&ctx,
165+
borrow.reason.as_ref(),
166+
DOMExceptionName::AbortError,
167+
)?;
164168
borrow.reason = Some(reason.clone());
165169
borrow.sender.send(reason);
166170
drop(borrow);
@@ -179,7 +183,8 @@ impl<'js> AbortSignal<'js> {
179183

180184
#[qjs(static)]
181185
pub fn timeout(ctx: Ctx<'js>, milliseconds: u64) -> Result<Class<'js, Self>> {
182-
let timeout_error = get_reason_or_dom_exception(&ctx, None, "TimeoutError")?;
186+
let timeout_error =
187+
get_reason_or_dom_exception(&ctx, None, DOMExceptionName::TimeoutError)?;
183188

184189
let signal = Self::new();
185190
let signal_instance = Class::instance(ctx.clone(), signal)?;
@@ -221,12 +226,12 @@ impl<'js> AbortSignal<'js> {
221226
fn get_reason_or_dom_exception<'js>(
222227
ctx: &Ctx<'js>,
223228
reason: Option<&Value<'js>>,
224-
name: &str,
229+
name: DOMExceptionName,
225230
) -> Result<Value<'js>> {
226231
let reason = if let Some(reason) = reason {
227232
reason.clone()
228233
} else {
229-
let ex = DOMException::new(ctx.clone(), Opt(None), Opt(Some(name.into())))?;
234+
let ex = DOMException::new_with_name(ctx, name, String::new())?;
230235
Class::instance(ctx.clone(), ex)?.into_value()
231236
};
232237
Ok(reason)

modules/llrt_exceptions/src/lib.rs

Lines changed: 125 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,43 @@
1-
use llrt_utils::primordials::{BasePrimordials, Primordial};
21
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
32
// SPDX-License-Identifier: Apache-2.0
4-
use rquickjs::{atom::PredefinedAtom, function::Opt, Class, Ctx, Object, Result};
3+
use llrt_utils::primordials::{BasePrimordials, Primordial};
4+
use rquickjs::{atom::PredefinedAtom, function::Opt, Class, Coerced, Ctx, Object, Result};
55

66
#[rquickjs::class]
77
#[derive(rquickjs::class::Trace, rquickjs::JsLifetime)]
88
pub struct DOMException {
9-
message: String,
109
name: String,
10+
message: String,
1111
stack: String,
1212
code: u8,
1313
}
1414

1515
#[rquickjs::methods]
1616
impl DOMException {
1717
#[qjs(constructor)]
18-
pub fn new(ctx: Ctx<'_>, message: Opt<String>, name: Opt<String>) -> Result<Self> {
19-
let primordials = BasePrimordials::get(&ctx)?;
18+
pub fn new(ctx: Ctx<'_>, message: Opt<String>, name: Opt<Coerced<String>>) -> Result<Self> {
19+
let message = message.0.unwrap_or_default();
20+
21+
let name = name
22+
.0
23+
.map(|name| DOMExceptionName::from(name.0))
24+
.unwrap_or(DOMExceptionName::Error);
25+
26+
Self::new_with_name(&ctx, name, message)
27+
}
28+
29+
#[qjs(skip)]
30+
pub fn new_with_name(ctx: &Ctx<'_>, name: DOMExceptionName, message: String) -> Result<Self> {
31+
let primordials = BasePrimordials::get(ctx)?;
2032

2133
let new: Object = primordials
2234
.constructor_error
2335
.construct((message.clone(),))?;
2436

25-
let message = message.0.unwrap_or(String::from(""));
26-
let name = name.0.unwrap_or(String::from("Error"));
27-
28-
// https://webidl.spec.whatwg.org/#dfn-error-names-table
29-
let code = match name.as_str() {
30-
"IndexSizeError" => 1,
31-
"HierarchyRequestError" => 3,
32-
"WrongDocumentError" => 4,
33-
"InvalidCharacterError" => 5,
34-
"NoModificationAllowedError" => 7,
35-
"NotFoundError" => 8,
36-
"NotSupportedError" => 9,
37-
"InUseAttributeError" => 10,
38-
"InvalidStateError" => 11,
39-
"SyntaxError" => 12,
40-
"InvalidModificationError" => 13,
41-
"NamespaceError" => 14,
42-
"InvalidAccessError" => 15,
43-
"TypeMismatchError" => 17,
44-
"SecurityError" => 18,
45-
"NetworkError" => 19,
46-
"AbortError" => 20,
47-
"URLMismatchError" => 21,
48-
"QuotaExceededError" => 22,
49-
"TimeoutError" => 23,
50-
"InvalidNodeTypeError" => 24,
51-
"DataCloneError" => 25,
52-
_ => 0,
53-
};
54-
5537
Ok(Self {
38+
name: format!("{:?}", name),
39+
code: name.code(),
5640
message,
57-
name,
58-
code,
5941
stack: new.get::<_, String>(PredefinedAtom::Stack)?,
6042
})
6143
}
@@ -66,8 +48,8 @@ impl DOMException {
6648
}
6749

6850
#[qjs(get)]
69-
pub fn name(&self) -> String {
70-
self.name.clone()
51+
pub fn name(&self) -> &str {
52+
self.name.as_str()
7153
}
7254

7355
#[qjs(get)]
@@ -84,10 +66,112 @@ impl DOMException {
8466
#[qjs(rename = PredefinedAtom::ToString)]
8567
pub fn to_string(&self) -> String {
8668
if self.message.is_empty() {
87-
return self.name.clone();
69+
return self.name().to_string();
8870
}
8971

90-
[self.name.as_str(), self.message.as_str()].join(": ")
72+
[self.name(), self.message.as_str()].join(": ")
73+
}
74+
}
75+
76+
macro_rules! create_dom_exception {
77+
($name:ident, $($variant:ident),+ $(,)?) => {
78+
#[derive(Debug)]
79+
pub enum $name {
80+
$(
81+
$variant,
82+
)+
83+
Other(String),
84+
}
85+
86+
impl $name {
87+
pub fn as_str(&self) -> &str {
88+
match self {
89+
$(
90+
Self::$variant => stringify!($variant),
91+
)+
92+
Self::Other(value) => value,
93+
}
94+
}
95+
}
96+
97+
impl From<String> for $name {
98+
fn from(value: String) -> Self {
99+
match value.as_str() {
100+
$(
101+
stringify!($variant) => Self::$variant,
102+
)+
103+
_ => Self::Other(value),
104+
}
105+
}
106+
}
107+
};
108+
}
109+
110+
// https://webidl.spec.whatwg.org/#dfn-error-names-table
111+
create_dom_exception!(
112+
DOMExceptionName,
113+
IndexSizeError,
114+
HierarchyRequestError,
115+
WrongDocumentError,
116+
InvalidCharacterError,
117+
NoModificationAllowedError,
118+
NotFoundError,
119+
NotSupportedError,
120+
InUseAttributeError,
121+
InvalidStateError,
122+
SyntaxError,
123+
InvalidModificationError,
124+
NamespaceError,
125+
InvalidAccessError,
126+
TypeMismatchError,
127+
SecurityError,
128+
NetworkError,
129+
AbortError,
130+
URLMismatchError,
131+
QuotaExceededError,
132+
TimeoutError,
133+
InvalidNodeTypeError,
134+
DataCloneError,
135+
EncodingError,
136+
NotReadableError,
137+
UnknownError,
138+
ConstraintError,
139+
DataError,
140+
TransactionInactiveError,
141+
ReadOnlyError,
142+
VersionError,
143+
OperationError,
144+
NotAllowedError,
145+
Error,
146+
);
147+
148+
impl DOMExceptionName {
149+
fn code(&self) -> u8 {
150+
match self {
151+
DOMExceptionName::IndexSizeError => 1,
152+
DOMExceptionName::HierarchyRequestError => 3,
153+
DOMExceptionName::WrongDocumentError => 4,
154+
DOMExceptionName::InvalidCharacterError => 5,
155+
DOMExceptionName::NoModificationAllowedError => 7,
156+
DOMExceptionName::NotFoundError => 8,
157+
DOMExceptionName::NotSupportedError => 9,
158+
DOMExceptionName::InUseAttributeError => 10,
159+
DOMExceptionName::InvalidStateError => 11,
160+
DOMExceptionName::SyntaxError => 12,
161+
DOMExceptionName::InvalidModificationError => 13,
162+
DOMExceptionName::NamespaceError => 14,
163+
DOMExceptionName::InvalidAccessError => 15,
164+
DOMExceptionName::TypeMismatchError => 17,
165+
DOMExceptionName::SecurityError => 18,
166+
DOMExceptionName::NetworkError => 19,
167+
DOMExceptionName::AbortError => 20,
168+
DOMExceptionName::URLMismatchError => 21,
169+
DOMExceptionName::QuotaExceededError => 22,
170+
DOMExceptionName::TimeoutError => 23,
171+
DOMExceptionName::InvalidNodeTypeError => 24,
172+
DOMExceptionName::DataCloneError => 25,
173+
_ => 0,
174+
}
91175
}
92176
}
93177

0 commit comments

Comments
 (0)