Skip to content

Commit 3700a94

Browse files
authored
Move the URL class to using the boa_class macro (#4294)
Instead of the js_class one which was weird to use. This is much cleaner and takes less space. Please note we cannot move Console, since it is not a class.
1 parent 864816b commit 3700a94

File tree

1 file changed

+152
-149
lines changed

1 file changed

+152
-149
lines changed

core/runtime/src/url.rs

Lines changed: 152 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
//! [spec]: https://url.spec.whatwg.org/
1111
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/URL
1212
#![cfg(feature = "url")]
13+
#![allow(clippy::needless_pass_by_value)]
1314

1415
#[cfg(test)]
1516
mod tests;
1617

18+
use boa_engine::class::Class;
1719
use boa_engine::value::Convert;
18-
use boa_engine::{
19-
js_error, js_string, Context, Finalize, JsData, JsResult, JsString, JsValue, Trace,
20-
};
21-
use boa_interop::{js_class, IntoJsFunctionCopied, JsClass};
20+
use boa_engine::{js_error, Context, Finalize, JsData, JsResult, JsString, JsValue, Trace};
21+
use boa_interop::boa_macros::boa_class;
2222
use std::fmt::Display;
2323

2424
/// The `URL` class represents a (properly parsed) Uniform Resource Locator.
@@ -35,13 +35,36 @@ impl Url {
3535
context.register_global_class::<Self>()?;
3636
Ok(())
3737
}
38+
}
39+
40+
impl Display for Url {
41+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42+
write!(f, "{}", self.0)
43+
}
44+
}
45+
46+
impl From<url::Url> for Url {
47+
fn from(url: url::Url) -> Self {
48+
Self(url)
49+
}
50+
}
51+
52+
impl From<Url> for url::Url {
53+
fn from(url: Url) -> url::Url {
54+
url.0
55+
}
56+
}
3857

58+
#[boa_class(rename = "URL")]
59+
#[boa(rename_all = "camelCase")]
60+
impl Url {
3961
/// Create a new `URL` object. Meant to be called from the JavaScript constructor.
4062
///
4163
/// # Errors
4264
/// Any errors that might occur during URL parsing.
43-
fn js_new(Convert(ref url): Convert<String>, base: Option<&Convert<String>>) -> JsResult<Self> {
44-
if let Some(Convert(base)) = base {
65+
#[boa(constructor)]
66+
pub fn new(Convert(ref url): Convert<String>, base: Option<Convert<String>>) -> JsResult<Self> {
67+
if let Some(Convert(ref base)) = base {
4568
let base_url = url::Url::parse(base)
4669
.map_err(|e| js_error!(TypeError: "Failed to parse base URL: {}", e))?;
4770
if base_url.cannot_be_a_base() {
@@ -58,179 +81,159 @@ impl Url {
5881
Ok(Self(url))
5982
}
6083
}
61-
}
6284

63-
impl Display for Url {
64-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65-
write!(f, "{}", self.0)
85+
#[boa(getter)]
86+
fn hash(&self) -> JsString {
87+
JsString::from(url::quirks::hash(&self.0))
6688
}
67-
}
6889

69-
impl From<url::Url> for Url {
70-
fn from(url: url::Url) -> Self {
71-
Self(url)
90+
#[boa(setter)]
91+
#[boa(rename = "hash")]
92+
fn set_hash(&mut self, value: Convert<String>) {
93+
url::quirks::set_hash(&mut self.0, &value.0);
7294
}
73-
}
7495

75-
impl From<Url> for url::Url {
76-
fn from(url: Url) -> url::Url {
77-
url.0
96+
#[boa(getter)]
97+
fn hostname(&self) -> JsString {
98+
JsString::from(url::quirks::hostname(&self.0))
7899
}
79-
}
80100

81-
js_class! {
82-
class Url as "URL" {
83-
property hash {
84-
fn get(this: JsClass<Url>) -> JsString {
85-
JsString::from(url::quirks::hash(&this.borrow().0))
86-
}
87-
88-
fn set(this: JsClass<Url>, value: Convert<String>) {
89-
url::quirks::set_hash(&mut this.borrow_mut().0, &value.0);
90-
}
91-
}
101+
#[boa(setter)]
102+
#[boa(rename = "hostname")]
103+
fn set_hostname(&mut self, value: Convert<String>) {
104+
let _ = url::quirks::set_hostname(&mut self.0, &value.0);
105+
}
92106

93-
property hostname {
94-
fn get(this: JsClass<Url>) -> JsString {
95-
JsString::from(url::quirks::hostname(&this.borrow().0))
96-
}
107+
#[boa(getter)]
108+
fn host(&self) -> JsString {
109+
JsString::from(url::quirks::host(&self.0))
110+
}
97111

98-
fn set(this: JsClass<Url>, value: Convert<String>) {
99-
let _ = url::quirks::set_hostname(&mut this.borrow_mut().0, &value.0);
100-
}
101-
}
112+
#[boa(setter)]
113+
#[boa(rename = "host")]
114+
fn set_host(&mut self, value: Convert<String>) {
115+
let _ = url::quirks::set_host(&mut self.0, &value.0);
116+
}
102117

103-
property host {
104-
fn get(this: JsClass<Url>) -> JsString {
105-
JsString::from(url::quirks::host(&this.borrow().0))
106-
}
118+
#[boa(getter)]
119+
fn href(&self) -> JsString {
120+
JsString::from(url::quirks::href(&self.0))
121+
}
107122

108-
fn set(this: JsClass<Url>, value: Convert<String>) {
109-
let _ = url::quirks::set_host(&mut this.borrow_mut().0, &value.0);
110-
}
111-
}
123+
#[boa(setter)]
124+
#[boa(rename = "href")]
125+
fn set_href(&mut self, value: Convert<String>) -> JsResult<()> {
126+
url::quirks::set_href(&mut self.0, &value.0)
127+
.map_err(|e| js_error!(TypeError: "Failed to set href: {}", e))
128+
}
112129

113-
property href {
114-
fn get(this: JsClass<Url>) -> JsString {
115-
JsString::from(url::quirks::href(&this.borrow().0))
116-
}
130+
#[boa(getter)]
131+
fn origin(&self) -> JsString {
132+
JsString::from(url::quirks::origin(&self.0))
133+
}
117134

118-
fn set(this: JsClass<Url>, value: Convert<String>) -> JsResult<()> {
119-
url::quirks::set_href(&mut this.borrow_mut().0, &value.0)
120-
.map_err(|e| js_error!(TypeError: "Failed to set href: {}", e))
121-
}
122-
}
135+
#[boa(getter)]
136+
fn password(&self) -> JsString {
137+
JsString::from(url::quirks::password(&self.0))
138+
}
123139

124-
property origin {
125-
fn get(this: JsClass<Url>) -> JsString {
126-
JsString::from(url::quirks::origin(&this.borrow().0))
127-
}
128-
}
140+
#[boa(setter)]
141+
#[boa(rename = "password")]
142+
fn set_password(&mut self, value: Convert<String>) {
143+
let _ = url::quirks::set_password(&mut self.0, &value.0);
144+
}
129145

130-
property password {
131-
fn get(this: JsClass<Url>) -> JsString {
132-
JsString::from(url::quirks::password(&this.borrow().0))
133-
}
146+
#[boa(getter)]
147+
fn pathname(&self) -> JsString {
148+
JsString::from(url::quirks::pathname(&self.0))
149+
}
134150

135-
fn set(this: JsClass<Url>, value: Convert<String>) {
136-
let _ = url::quirks::set_password(&mut this.borrow_mut().0, &value.0);
137-
}
138-
}
151+
#[boa(setter)]
152+
#[boa(rename = "pathname")]
153+
fn set_pathname(&mut self, value: Convert<String>) {
154+
let () = url::quirks::set_pathname(&mut self.0, &value.0);
155+
}
139156

140-
property pathname {
141-
fn get(this: JsClass<Url>) -> JsString {
142-
JsString::from(url::quirks::pathname(&this.borrow().0))
143-
}
157+
#[boa(getter)]
158+
fn port(&self) -> JsString {
159+
JsString::from(url::quirks::port(&self.0))
160+
}
144161

145-
fn set(this: JsClass<Url>, value: Convert<String>) {
146-
let () = url::quirks::set_pathname(&mut this.borrow_mut().0, &value.0);
147-
}
148-
}
162+
#[boa(setter)]
163+
#[boa(rename = "port")]
164+
fn set_port(&mut self, value: Convert<JsString>) {
165+
let _ = url::quirks::set_port(&mut self.0, &value.0.to_std_string_lossy());
166+
}
149167

150-
property port {
151-
fn get(this: JsClass<Url>) -> JsString {
152-
JsString::from(url::quirks::port(&this.borrow().0))
153-
}
168+
#[boa(getter)]
169+
fn protocol(&self) -> JsString {
170+
JsString::from(url::quirks::protocol(&self.0))
171+
}
154172

155-
fn set(this: JsClass<Url>, value: Convert<JsString>) {
156-
let _ = url::quirks::set_port(&mut this.borrow_mut().0, &value.0.to_std_string_lossy());
157-
}
158-
}
173+
#[boa(setter)]
174+
#[boa(rename = "protocol")]
175+
fn set_protocol(&mut self, value: Convert<String>) {
176+
let _ = url::quirks::set_protocol(&mut self.0, &value.0);
177+
}
159178

160-
property protocol {
161-
fn get(this: JsClass<Url>) -> JsString {
162-
JsString::from(url::quirks::protocol(&this.borrow().0))
163-
}
179+
#[boa(getter)]
180+
fn search(&self) -> JsString {
181+
JsString::from(url::quirks::search(&self.0))
182+
}
164183

165-
fn set(this: JsClass<Url>, value: Convert<String>) {
166-
let _ = url::quirks::set_protocol(&mut this.borrow_mut().0, &value.0);
167-
}
168-
}
184+
#[boa(setter)]
185+
#[boa(rename = "search")]
186+
fn set_search(&mut self, value: Convert<String>) {
187+
url::quirks::set_search(&mut self.0, &value.0);
188+
}
169189

170-
property search {
171-
fn get(this: JsClass<Url>) -> JsString {
172-
JsString::from(url::quirks::search(&this.borrow().0))
173-
}
190+
#[boa(getter)]
191+
fn search_params() -> JsResult<()> {
192+
Err(js_error!(Error: "URL.searchParams is not implemented"))
193+
}
174194

175-
fn set(this: JsClass<Url>, value: Convert<String>) {
176-
url::quirks::set_search(&mut this.borrow_mut().0, &value.0);
177-
}
178-
}
195+
#[boa(getter)]
196+
fn username(&self) -> JsString {
197+
JsString::from(self.0.username())
198+
}
179199

180-
property search_params as "searchParams" {
181-
fn get() -> JsResult<()> {
182-
Err(js_error!(Error: "URL.searchParams is not implemented"))
183-
}
184-
}
200+
#[boa(setter)]
201+
#[boa(rename = "username")]
202+
fn set_username(&mut self, value: Convert<String>) {
203+
let _ = self.0.set_username(&value.0);
204+
}
185205

186-
property username {
187-
fn get(this: JsClass<Url>) -> JsString {
188-
JsString::from(this.borrow().0.username())
189-
}
206+
fn to_string(&self) -> JsString {
207+
JsString::from(format!("{}", self.0))
208+
}
190209

191-
fn set(this: JsClass<Url>, value: Convert<String>) {
192-
let _ = this.borrow_mut().0.set_username(&value.0);
193-
}
194-
}
210+
fn to_json(&self) -> JsString {
211+
JsString::from(format!("{}", self.0))
212+
}
195213

196-
constructor(url: Convert<String>, base: Option<Convert<String>>) {
197-
Self::js_new(url, base.as_ref())
198-
}
214+
#[boa(static)]
215+
fn create_object_url() -> JsResult<()> {
216+
Err(js_error!(Error: "URL.createObjectURL is not implemented"))
217+
}
199218

200-
init(class: &mut ClassBuilder) -> JsResult<()> {
201-
let create_object_url = (|| -> JsResult<()> {
202-
Err(js_error!(Error: "URL.createObjectURL is not implemented"))
203-
})
204-
.into_js_function_copied(class.context());
205-
let can_parse = (|url: Convert<String>, base: Option<Convert<String>>| {
206-
Url::js_new(url, base.as_ref()).is_ok()
207-
})
208-
.into_js_function_copied(class.context());
209-
let parse = (|url: Convert<String>, base: Option<Convert<String>>, context: &mut Context| {
210-
Url::js_new(url, base.as_ref())
211-
.map_or(Ok(JsValue::null()), |u| Url::from_data(u, context).map(JsValue::from))
212-
})
213-
.into_js_function_copied(class.context());
214-
let revoke_object_url = (|| -> JsResult<()> {
215-
Err(js_error!(Error: "URL.revokeObjectURL is not implemented"))
216-
})
217-
.into_js_function_copied(class.context());
218-
219-
class
220-
.static_method(js_string!("createObjectURL"), 1, create_object_url)
221-
.static_method(js_string!("canParse"), 2, can_parse)
222-
.static_method(js_string!("parse"), 2, parse)
223-
.static_method(js_string!("revokeObjectUrl"), 1, revoke_object_url);
224-
225-
Ok(())
226-
}
219+
#[boa(static)]
220+
fn can_parse(url: Convert<String>, base: Option<Convert<String>>) -> bool {
221+
Url::new(url, base).is_ok()
222+
}
227223

228-
fn to_string as "toString"(this: JsClass<Url>) -> JsString {
229-
JsString::from(format!("{}", this.borrow().0))
230-
}
224+
#[boa(static)]
225+
fn parse(
226+
url: Convert<String>,
227+
base: Option<Convert<String>>,
228+
context: &mut Context,
229+
) -> JsResult<JsValue> {
230+
Url::new(url, base).map_or(Ok(JsValue::null()), |u| {
231+
Url::from_data(u, context).map(JsValue::from)
232+
})
233+
}
231234

232-
fn to_json as "toJSON"(this: JsClass<Url>) -> JsString {
233-
JsString::from(format!("{}", this.borrow().0))
234-
}
235+
#[boa(static)]
236+
fn revoke_object_url() -> JsResult<()> {
237+
Err(js_error!(Error: "URL.revokeObjectURL is not implemented"))
235238
}
236239
}

0 commit comments

Comments
 (0)