Skip to content

Commit 49eea1c

Browse files
authored
Fix multiple issues on wasm32: (#886)
* remove `Url::socket_addrs` on wasm32-unknown-unknown (it won't work, those platform API calls are not supported) * disable unit tests which won't work on wasm32-unknown-unknown * run tests in `wasm_bindgen_test` on wasm32-unknown-unknown * remove `panic::catch_unwind` from wpt tests, as that conflicts with wasm-bindgen's panic handler * run the tests in CI
1 parent a4dd58b commit 49eea1c

File tree

5 files changed

+126
-60
lines changed

5 files changed

+126
-60
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ jobs:
5959
- uses: dtolnay/rust-toolchain@stable
6060
with:
6161
targets: wasm32-unknown-unknown
62+
- name: Install wasm-pack
63+
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
6264
- run: cargo build --target wasm32-unknown-unknown
65+
- run: cd url && wasm-pack test --headless --chrome
66+
- run: cd url && wasm-pack test --headless --firefox
6367

6468
Lint:
6569
runs-on: ubuntu-latest

url/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ serde = { version = "1.0", features = ["derive"] }
2121
serde_json = "1.0"
2222
bencher = "0.1"
2323

24+
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies]
25+
wasm-bindgen-test = "0.3"
26+
2427
[dependencies]
2528
form_urlencoded = { version = "1.2.1", path = "../form_urlencoded" }
2629
idna = { version = "0.5.0", path = "../idna" }

url/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,12 @@ use std::borrow::Borrow;
154154
use std::cmp;
155155
use std::fmt::{self, Write};
156156
use std::hash;
157+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
157158
use std::io;
158159
use std::mem;
159-
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
160+
use std::net::IpAddr;
161+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
162+
use std::net::{SocketAddr, ToSocketAddrs};
160163
use std::ops::{Range, RangeFrom, RangeTo};
161164
use std::path::{Path, PathBuf};
162165
use std::str;
@@ -1252,6 +1255,7 @@ impl Url {
12521255
/// })
12531256
/// }
12541257
/// ```
1258+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
12551259
pub fn socket_addrs(
12561260
&self,
12571261
default_port_number: impl Fn() -> Option<u16>,

url/tests/unit.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
use std::borrow::Cow;
1212
use std::cell::{Cell, RefCell};
1313
use std::net::{Ipv4Addr, Ipv6Addr};
14+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
1415
use std::path::{Path, PathBuf};
1516
use url::{form_urlencoded, Host, Origin, Url};
1617

18+
// https://rustwasm.github.io/wasm-bindgen/wasm-bindgen-test/usage.html
19+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
20+
use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
21+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
22+
wasm_bindgen_test_configure!(run_in_browser);
23+
1724
#[test]
1825
fn size() {
1926
use std::mem::size_of;
@@ -117,6 +124,7 @@ fn test_set_empty_query() {
117124
assert_eq!(base.as_str(), "moz://example.com/path");
118125
}
119126

127+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
120128
macro_rules! assert_from_file_path {
121129
($path: expr) => {
122130
assert_from_file_path!($path, $path)
@@ -130,6 +138,7 @@ macro_rules! assert_from_file_path {
130138
}
131139

132140
#[test]
141+
#[cfg(any(unix, windows))]
133142
fn new_file_paths() {
134143
if cfg!(unix) {
135144
assert_eq!(Url::from_file_path(Path::new("relative")), Err(()));
@@ -162,28 +171,28 @@ fn new_path_bad_utf8() {
162171
}
163172

164173
#[test]
174+
#[cfg(windows)]
165175
fn new_path_windows_fun() {
166-
if cfg!(windows) {
167-
assert_from_file_path!(r"C:\foo\bar", "/C:/foo/bar");
168-
assert_from_file_path!("C:\\foo\\ba\0r", "/C:/foo/ba%00r");
176+
assert_from_file_path!(r"C:\foo\bar", "/C:/foo/bar");
177+
assert_from_file_path!("C:\\foo\\ba\0r", "/C:/foo/ba%00r");
169178

170-
// Invalid UTF-8
171-
assert!(Url::parse("file:///C:/foo/ba%80r")
172-
.unwrap()
173-
.to_file_path()
174-
.is_err());
179+
// Invalid UTF-8
180+
assert!(Url::parse("file:///C:/foo/ba%80r")
181+
.unwrap()
182+
.to_file_path()
183+
.is_err());
175184

176-
// test windows canonicalized path
177-
let path = PathBuf::from(r"\\?\C:\foo\bar");
178-
assert!(Url::from_file_path(path).is_ok());
185+
// test windows canonicalized path
186+
let path = PathBuf::from(r"\\?\C:\foo\bar");
187+
assert!(Url::from_file_path(path).is_ok());
179188

180-
// Percent-encoded drive letter
181-
let url = Url::parse("file:///C%3A/foo/bar").unwrap();
182-
assert_eq!(url.to_file_path(), Ok(PathBuf::from(r"C:\foo\bar")));
183-
}
189+
// Percent-encoded drive letter
190+
let url = Url::parse("file:///C%3A/foo/bar").unwrap();
191+
assert_eq!(url.to_file_path(), Ok(PathBuf::from(r"C:\foo\bar")));
184192
}
185193

186194
#[test]
195+
#[cfg(any(unix, windows))]
187196
fn new_directory_paths() {
188197
if cfg!(unix) {
189198
assert_eq!(Url::from_directory_path(Path::new("relative")), Err(()));
@@ -439,6 +448,7 @@ fn issue_61() {
439448
}
440449

441450
#[test]
451+
#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
442452
#[cfg(not(windows))]
443453
/// https://github.com/servo/rust-url/issues/197
444454
fn issue_197() {
@@ -623,6 +633,7 @@ fn test_origin_unicode_serialization() {
623633
}
624634

625635
#[test]
636+
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
626637
fn test_socket_addrs() {
627638
use std::net::ToSocketAddrs;
628639

@@ -804,11 +815,8 @@ fn test_expose_internals() {
804815
}
805816

806817
#[test]
818+
#[cfg(windows)]
807819
fn test_windows_unc_path() {
808-
if !cfg!(windows) {
809-
return;
810-
}
811-
812820
let url = Url::from_file_path(Path::new(r"\\host\share\path\file.txt")).unwrap();
813821
assert_eq!(url.as_str(), "file://host/share/path/file.txt");
814822

@@ -928,6 +936,7 @@ fn test_url_from_file_path() {
928936
}
929937

930938
/// https://github.com/servo/rust-url/issues/505
939+
#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
931940
#[cfg(not(windows))]
932941
#[test]
933942
fn test_url_from_file_path() {

url/tests/wpt.rs

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,62 @@
88

99
//! Data-driven tests imported from web-platform-tests
1010
11+
use serde_json::Value;
1112
use std::collections::HashMap;
1213
use std::fmt::Write;
13-
use std::panic;
14-
15-
use serde_json::Value;
14+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
15+
use std::sync::Mutex;
1616
use url::Url;
1717

18+
// https://rustwasm.github.io/wasm-bindgen/wasm-bindgen-test/usage.html
19+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
20+
use wasm_bindgen_test::{console_log, wasm_bindgen_test, wasm_bindgen_test_configure};
21+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
22+
wasm_bindgen_test_configure!(run_in_browser);
23+
24+
// wpt has its own test driver, but we shoe-horn this into wasm_bindgen_test
25+
// which will discard stdout and stderr. So, we make println! go to
26+
// console.log(), so we see failures that do not result in panics.
27+
28+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
29+
static PRINT_BUF: Mutex<Option<String>> = Mutex::new(None);
30+
31+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
32+
macro_rules! print {
33+
($($arg:tt)*) => {
34+
let v = format!($($arg)*);
35+
{
36+
let mut buf = PRINT_BUF.lock().unwrap();
37+
if let Some(buf) = buf.as_mut() {
38+
buf.push_str(&v);
39+
} else {
40+
*buf = Some(v);
41+
}
42+
}
43+
};
44+
}
45+
46+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
47+
macro_rules! println {
48+
() => {
49+
let buf = PRINT_BUF.lock().unwrap().take();
50+
match buf {
51+
Some(buf) => console_log!("{buf}"),
52+
None => console_log!(""),
53+
}
54+
};
55+
($($arg:tt)*) => {
56+
let buf = PRINT_BUF.lock().unwrap().take();
57+
match buf {
58+
Some(buf) => {
59+
let v = format!($($arg)*);
60+
console_log!("{buf}{v}");
61+
},
62+
None => console_log!($($arg)*),
63+
}
64+
}
65+
}
66+
1867
#[derive(Debug, serde::Deserialize)]
1968
struct UrlTest {
2069
input: String,
@@ -71,6 +120,7 @@ struct SetterTestExpected {
71120
hash: Option<String>,
72121
}
73122

123+
#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), wasm_bindgen_test)]
74124
fn main() {
75125
let mut filter = None;
76126
let mut args = std::env::args().skip(1);
@@ -228,16 +278,16 @@ fn run_url_test(
228278
) -> Result<(), String> {
229279
let base = match base {
230280
Some(base) => {
231-
let base = panic::catch_unwind(|| Url::parse(&base))
232-
.map_err(|_| "panicked while parsing base".to_string())?
233-
.map_err(|e| format!("errored while parsing base: {}", e))?;
281+
let base =
282+
Url::parse(&base).map_err(|e| format!("errored while parsing base: {}", e))?;
234283
Some(base)
235284
}
236285
None => None,
237286
};
238287

239-
let res = panic::catch_unwind(move || Url::options().base_url(base.as_ref()).parse(&input))
240-
.map_err(|_| "panicked while parsing input".to_string())?
288+
let res = Url::options()
289+
.base_url(base.as_ref())
290+
.parse(&input)
241291
.map_err(|e| format!("errored while parsing input: {}", e));
242292

243293
match result {
@@ -340,38 +390,34 @@ fn run_setter_test(
340390
expected,
341391
}: SetterTest,
342392
) -> Result<(), String> {
343-
let mut url = panic::catch_unwind(|| Url::parse(&href))
344-
.map_err(|_| "panicked while parsing href".to_string())?
345-
.map_err(|e| format!("errored while parsing href: {}", e))?;
346-
347-
let url = panic::catch_unwind(move || {
348-
match kind {
349-
"protocol" => {
350-
url::quirks::set_protocol(&mut url, &new_value).ok();
351-
}
352-
"username" => {
353-
url::quirks::set_username(&mut url, &new_value).ok();
354-
}
355-
"password" => {
356-
url::quirks::set_password(&mut url, &new_value).ok();
357-
}
358-
"host" => {
359-
url::quirks::set_host(&mut url, &new_value).ok();
360-
}
361-
"hostname" => {
362-
url::quirks::set_hostname(&mut url, &new_value).ok();
363-
}
364-
"port" => {
365-
url::quirks::set_port(&mut url, &new_value).ok();
366-
}
367-
"pathname" => url::quirks::set_pathname(&mut url, &new_value),
368-
"search" => url::quirks::set_search(&mut url, &new_value),
369-
"hash" => url::quirks::set_hash(&mut url, &new_value),
370-
_ => panic!("unknown setter kind: {:?}", kind),
371-
};
372-
url
373-
})
374-
.map_err(|_| "panicked while setting value".to_string())?;
393+
let mut url = Url::parse(&href).map_err(|e| format!("errored while parsing href: {}", e))?;
394+
395+
match kind {
396+
"protocol" => {
397+
url::quirks::set_protocol(&mut url, &new_value).ok();
398+
}
399+
"username" => {
400+
url::quirks::set_username(&mut url, &new_value).ok();
401+
}
402+
"password" => {
403+
url::quirks::set_password(&mut url, &new_value).ok();
404+
}
405+
"host" => {
406+
url::quirks::set_host(&mut url, &new_value).ok();
407+
}
408+
"hostname" => {
409+
url::quirks::set_hostname(&mut url, &new_value).ok();
410+
}
411+
"port" => {
412+
url::quirks::set_port(&mut url, &new_value).ok();
413+
}
414+
"pathname" => url::quirks::set_pathname(&mut url, &new_value),
415+
"search" => url::quirks::set_search(&mut url, &new_value),
416+
"hash" => url::quirks::set_hash(&mut url, &new_value),
417+
_ => {
418+
return Err(format!("unknown setter kind: {:?}", kind));
419+
}
420+
}
375421

376422
if let Some(expected_href) = expected.href {
377423
let href = url::quirks::href(&url);

0 commit comments

Comments
 (0)