1use idna::domain_to_ascii_strict;
8use ion::function::Opt;
9use ion::{ClassDefinition as _, Context, Object, Result, function_spec, js_fn};
10use mozjs::jsapi::JSFunctionSpec;
11use runtime::globals::url::{URL, URLSearchParams};
12use runtime::module::NativeModule;
13
14#[js_fn]
15fn domain_to_ascii(domain: String, Opt(strict): Opt<bool>) -> Result<String> {
16 let strict = strict.unwrap_or(false);
17 let domain = if !strict {
18 idna::domain_to_ascii(&domain)
19 } else {
20 domain_to_ascii_strict(&domain)
21 };
22 domain.map_err(Into::into)
23}
24
25#[js_fn]
26fn domain_to_unicode(domain: String) -> String {
27 idna::domain_to_unicode(&domain).0
28}
29
30const FUNCTIONS: &[JSFunctionSpec] = &[
31 function_spec!(domain_to_ascii, c"domainToASCII", 0),
32 function_spec!(domain_to_unicode, c"domainToUnicode", 0),
33 JSFunctionSpec::ZERO,
34];
35
36pub struct UrlM;
37
38impl<'cx> NativeModule<'cx> for UrlM {
39 const NAME: &'static str = "url";
40 const VARIABLE_NAME: &'static str = "url";
41 const SOURCE: &'static str = include_str!("url.js");
42
43 fn module(&self, cx: &'cx Context) -> Option<Object<'cx>> {
44 let url = Object::new(cx);
45 let global = Object::global(cx);
46
47 if unsafe { url.define_methods(cx, FUNCTIONS) } {
48 if let Some(global_url) = global.get(cx, "URL").unwrap() {
49 url.set(cx, "URL", &global_url);
50 } else {
51 URL::init_class(cx, &url);
52 }
53
54 if let Some(url_search_params) = global.get(cx, "URLSearchParams").unwrap() {
55 url.set(cx, "URLSearchParams", &url_search_params);
56 } else {
57 URLSearchParams::init_class(cx, &url);
58 }
59
60 return Some(url);
61 }
62 None
63 }
64}