Skip to content

Commit 9bab720

Browse files
authored
Merge pull request #175 from rustwasm/non-wasm
Enable `cargo test` where possible
2 parents 98f3b96 + 4a873af commit 9bab720

File tree

4 files changed

+188
-57
lines changed

4 files changed

+188
-57
lines changed

crates/backend/src/codegen.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ impl ToTokens for ast::Struct {
155155
impl ::wasm_bindgen::__rt::core::convert::From<#name> for
156156
::wasm_bindgen::JsValue
157157
{
158+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
158159
fn from(value: #name) -> Self {
159160
let ptr = ::wasm_bindgen::convert::IntoWasmAbi::into_abi(
160161
value,
@@ -174,8 +175,14 @@ impl ToTokens for ast::Struct {
174175
)
175176
}
176177
}
178+
179+
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
180+
fn from(_value: #name) -> Self {
181+
panic!("cannot convert to JsValue outside of the wasm target")
182+
}
177183
}
178184

185+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
179186
#[no_mangle]
180187
pub unsafe extern fn #free_fn(ptr: u32) {
181188
<#name as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
@@ -229,6 +236,7 @@ impl ToTokens for ast::StructField {
229236
let desc = syn::Ident::from(format!("__wbindgen_describe_{}", getter));
230237
(quote! {
231238
#[no_mangle]
239+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
232240
pub unsafe extern fn #getter(js: u32)
233241
-> <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
234242
{
@@ -260,6 +268,7 @@ impl ToTokens for ast::StructField {
260268

261269
(quote! {
262270
#[no_mangle]
271+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
263272
pub unsafe extern fn #setter(
264273
js: u32,
265274
val: <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi,
@@ -395,6 +404,7 @@ impl ToTokens for ast::Export {
395404
let tokens = quote! {
396405
#[export_name = #export_name]
397406
#[allow(non_snake_case)]
407+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
398408
pub extern fn #generated_name(#(#args),*) #ret_ty {
399409
::wasm_bindgen::__rt::link_this_library();
400410
let #ret = {
@@ -424,6 +434,7 @@ impl ToTokens for ast::Export {
424434
// this, but the tl;dr; is that this is stripped from the final wasm
425435
// binary along with anything it references.
426436
#[no_mangle]
437+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
427438
pub extern fn #descriptor_name() {
428439
use wasm_bindgen::describe::*;
429440
inform(FUNCTION);
@@ -640,6 +651,7 @@ impl ToTokens for ast::ImportFunction {
640651
.iter()
641652
.skip(if is_method { 1 } else { 0 })
642653
.collect::<Vec<_>>();
654+
let arguments = &arguments[..];
643655

644656
let me = if is_method {
645657
quote! { &self, }
@@ -650,6 +662,7 @@ impl ToTokens for ast::ImportFunction {
650662
let invocation = quote! {
651663
#(#attrs)*
652664
#[allow(bad_style)]
665+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
653666
#vis extern #fn_token #rust_name(#me #(#arguments),*) #ret {
654667
::wasm_bindgen::__rt::link_this_library();
655668
#[wasm_import_module = "__wbindgen_placeholder__"]
@@ -668,6 +681,14 @@ impl ToTokens for ast::ImportFunction {
668681
}
669682
}
670683

684+
#(#attrs)*
685+
#[allow(bad_style, unused_variables)]
686+
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
687+
#vis extern #fn_token #rust_name(#me #(#arguments),*) #ret {
688+
panic!("cannot call wasm-bindgen imported functions on \
689+
non-wasm targets");
690+
}
691+
671692
};
672693

673694
if let Some(class) = class_ty {
@@ -766,6 +787,7 @@ impl ToTokens for ast::ImportStatic {
766787
(quote! {
767788
#[allow(bad_style)]
768789
#vis static #name: ::wasm_bindgen::JsStatic<#ty> = {
790+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
769791
fn init() -> #ty {
770792
#[wasm_import_module = "__wbindgen_placeholder__"]
771793
extern {
@@ -779,6 +801,10 @@ impl ToTokens for ast::ImportStatic {
779801

780802
}
781803
}
804+
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
805+
fn init() -> #ty {
806+
panic!("cannot access imported statics on non-wasm targets")
807+
}
782808
static mut _VAL: ::wasm_bindgen::__rt::core::cell::UnsafeCell<Option<#ty>> =
783809
::wasm_bindgen::__rt::core::cell::UnsafeCell::new(None);
784810
::wasm_bindgen::JsStatic {

src/lib.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,27 @@ macro_rules! numbers {
275275

276276
numbers! { i8 u8 i16 u16 i32 u32 f32 f64 }
277277

278-
#[wasm_import_module = "__wbindgen_placeholder__"]
279-
extern {
278+
macro_rules! externs {
279+
($(fn $name:ident($($args:tt)*) -> $ret:ty;)*) => (
280+
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
281+
#[wasm_import_module = "__wbindgen_placeholder__"]
282+
extern {
283+
$(fn $name($($args)*) -> $ret;)*
284+
}
285+
286+
$(
287+
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
288+
#[allow(unused_variables)]
289+
unsafe extern fn $name($($args)*) -> $ret {
290+
panic!("function not implemented on non-wasm32 targets")
291+
}
292+
)*
293+
)
294+
}
295+
296+
externs! {
280297
fn __wbindgen_object_clone_ref(idx: u32) -> u32;
281-
fn __wbindgen_object_drop_ref(idx: u32);
298+
fn __wbindgen_object_drop_ref(idx: u32) -> ();
282299
fn __wbindgen_string_new(ptr: *const u8, len: usize) -> u32;
283300
fn __wbindgen_number_new(f: f64) -> u32;
284301
fn __wbindgen_number_get(idx: u32, invalid: *mut u8) -> f64;
@@ -293,10 +310,10 @@ extern {
293310
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
294311
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
295312

296-
fn __wbindgen_cb_drop(idx: u32);
297-
fn __wbindgen_cb_forget(idx: u32);
313+
fn __wbindgen_cb_drop(idx: u32) -> ();
314+
fn __wbindgen_cb_forget(idx: u32) -> ();
298315

299-
fn __wbindgen_describe(v: u32);
316+
fn __wbindgen_describe(v: u32) -> ();
300317

301318
fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32;
302319
fn __wbindgen_json_serialize(idx: u32, ptr: *mut *mut u8) -> usize;

tests/all/main.rs

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct Project {
1717
node: bool,
1818
no_std: bool,
1919
serde: bool,
20+
rlib: bool,
21+
deps: Vec<String>,
2022
}
2123

2224
fn project() -> Project {
@@ -29,23 +31,9 @@ fn project() -> Project {
2931
node: false,
3032
no_std: false,
3133
serde: false,
34+
rlib: false,
35+
deps: Vec::new(),
3236
files: vec![
33-
("Cargo.toml".to_string(), format!(r#"
34-
[package]
35-
name = "test{}"
36-
version = "0.0.1"
37-
authors = []
38-
39-
[workspace]
40-
41-
[lib]
42-
crate-type = ["cdylib"]
43-
44-
# XXX: It is important that `[dependencies]` is the last section
45-
# here, so that `add_local_dependency` functions correctly!
46-
[dependencies]
47-
"#, IDX.with(|x| *x))),
48-
4937
("Cargo.lock".to_string(), lockfile),
5038

5139
("run.js".to_string(), r#"
@@ -158,59 +146,72 @@ impl Project {
158146
self
159147
}
160148

149+
fn rlib(&mut self, rlib: bool) -> &mut Project {
150+
self.rlib = rlib;
151+
self
152+
}
153+
161154
fn depend(&mut self, dep: &str) -> &mut Project {
162-
{
163-
let cargo_toml = self.files
164-
.iter_mut()
165-
.find(|f| f.0 == "Cargo.toml")
166-
.expect("should have Cargo.toml file!");
167-
cargo_toml.1.push_str(dep);
168-
cargo_toml.1.push_str("\n");
169-
}
155+
self.deps.push(dep.to_string());
170156
self
171157
}
172158

173159
fn add_local_dependency(&mut self, name: &str, path: &str) -> &mut Project {
174-
{
175-
let cargo_toml = self.files
176-
.iter_mut()
177-
.find(|f| f.0 == "Cargo.toml")
178-
.expect("should have Cargo.toml file!");
179-
cargo_toml.1.push_str(name);
180-
cargo_toml.1.push_str(" = { path = '");
181-
cargo_toml.1.push_str(path);
182-
cargo_toml.1.push_str("' }\n");
183-
}
160+
self.deps.push(format!("{} = {{ path = '{}' }}", name, path));
184161
self
185162
}
186163

187-
fn test(&mut self) {
188-
{
189-
let cargo_toml = self.files
190-
.iter_mut()
191-
.find(|f| f.0 == "Cargo.toml")
192-
.expect("should have Cargo.toml file!");
193-
cargo_toml.1.push_str("wasm-bindgen = { path = '");
194-
cargo_toml.1.push_str(env!("CARGO_MANIFEST_DIR"));
195-
cargo_toml.1.push_str("'");
196-
if self.no_std {
197-
cargo_toml.1.push_str(", default-features = false");
198-
}
199-
if self.serde {
200-
cargo_toml.1.push_str(", features = ['serde-serialize']");
201-
}
202-
cargo_toml.1.push_str(" }\n");
164+
fn crate_name(&self) -> String {
165+
format!("test{}", IDX.with(|x| *x))
166+
}
167+
168+
fn build(&mut self) -> (PathBuf, PathBuf) {
169+
let mut manifest = format!(r#"
170+
[package]
171+
name = "test{}"
172+
version = "0.0.1"
173+
authors = []
174+
175+
[workspace]
176+
177+
[lib]
178+
"#, IDX.with(|x| *x));
179+
180+
if !self.rlib {
181+
manifest.push_str("crate-type = [\"cdylib\"]\n");
182+
}
183+
184+
manifest.push_str("[dependencies]\n");
185+
for dep in self.deps.iter() {
186+
manifest.push_str(dep);
187+
manifest.push_str("\n");
188+
}
189+
manifest.push_str("wasm-bindgen = { path = '");
190+
manifest.push_str(env!("CARGO_MANIFEST_DIR"));
191+
manifest.push_str("'");
192+
if self.no_std {
193+
manifest.push_str(", default-features = false");
203194
}
195+
if self.serde {
196+
manifest.push_str(", features = ['serde-serialize']");
197+
}
198+
manifest.push_str(" }\n");
199+
self.files.push(("Cargo.toml".to_string(), manifest));
200+
204201
let root = root();
205202
drop(fs::remove_dir_all(&root));
206203
for &(ref file, ref contents) in self.files.iter() {
207204
let dst = root.join(file);
208205
fs::create_dir_all(dst.parent().unwrap()).unwrap();
209206
fs::File::create(&dst).unwrap().write_all(contents.as_ref()).unwrap();
210207
}
211-
212208
let target_dir = root.parent().unwrap() // chop off test name
213209
.parent().unwrap(); // chop off `generated-tests`
210+
(root.clone(), target_dir.to_path_buf())
211+
}
212+
213+
fn test(&mut self) {
214+
let (root, target_dir) = self.build();
214215

215216
let mut cmd = Command::new("cargo");
216217
cmd.arg("build")
@@ -333,3 +334,4 @@ mod non_debug;
333334
mod simple;
334335
mod slice;
335336
mod structural;
337+
mod non_wasm;

tests/all/non_wasm.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use std::process::Command;
2+
use super::{run, project};
3+
4+
#[test]
5+
fn works() {
6+
let mut p = project();
7+
let name = p.crate_name();
8+
p
9+
.rlib(true)
10+
.file("src/lib.rs", r#"
11+
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
12+
13+
extern crate wasm_bindgen;
14+
15+
use wasm_bindgen::prelude::*;
16+
17+
#[wasm_bindgen]
18+
pub struct A {
19+
x: u32,
20+
}
21+
22+
#[wasm_bindgen]
23+
impl A {
24+
pub fn new() -> A {
25+
A { x: 3 }
26+
}
27+
28+
pub fn foo(&self) {
29+
}
30+
}
31+
32+
#[wasm_bindgen]
33+
pub fn foo(x: bool) {
34+
A::new().foo();
35+
36+
if x {
37+
bar("test");
38+
baz(JsValue::from(3));
39+
}
40+
}
41+
42+
#[wasm_bindgen]
43+
extern {
44+
fn some_import();
45+
static A: JsValue;
46+
}
47+
48+
#[wasm_bindgen]
49+
pub fn bar(_: &str) -> JsValue {
50+
some_import();
51+
A.clone()
52+
}
53+
54+
#[wasm_bindgen]
55+
pub fn baz(_: JsValue) {
56+
}
57+
"#)
58+
.file("tests/foo.rs", &format!("
59+
extern crate {} as mytest;
60+
61+
#[test]
62+
fn foo() {{
63+
mytest::foo(false);
64+
mytest::A::new().foo();
65+
}}
66+
", name))
67+
.file("benches/foo.rs", &format!("
68+
#![feature(test)]
69+
extern crate test;
70+
extern crate {} as mytest;
71+
72+
#[bench]
73+
fn foo(b: &mut test::Bencher) {{
74+
b.iter(|| mytest::foo(false));
75+
}}
76+
", name));
77+
let (root, target_dir) = p.build();
78+
let mut cmd = Command::new("cargo");
79+
cmd.arg("test")
80+
.arg("--test").arg("foo")
81+
.arg("--bench").arg("foo")
82+
.current_dir(&root)
83+
.env("CARGO_TARGET_DIR", &target_dir);
84+
run(&mut cmd, "cargo");
85+
}
86+

0 commit comments

Comments
 (0)