diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d18aac7b127..de957ca79e4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,12 +67,12 @@ jobs: - run: cargo clippy --no-deps --all-features -p example-tests -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-externref-xform -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-futures -- -D warnings - - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro -- -D warnings - - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro-support -- -D warnings + - run: cargo clippy --no-deps --features spans,strict-macro -p wasm-bindgen-macro -- -D warnings + - run: cargo clippy --no-deps --features extra-traits,spans,strict-macro -p wasm-bindgen-macro-support -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-multi-value-xform -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-shared -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-test -- -D warnings - - run: cargo clippy --no-deps --all-features -p wasm-bindgen-test-macro -- -D warnings + - run: cargo clippy --no-deps -p wasm-bindgen-test-macro -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-threads-xform -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p typescript-tests -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-wasm-conventions -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index 153a7306e31..f7992176e8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,11 @@ wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.95", default-featu "atomics", ] } +[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"), wasm_bindgen_unstable_test_coverage))'.dependencies] +wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.95", default-features = false, features = [ + "coverage", +] } + [dev-dependencies] wasm-bindgen-test = { path = 'crates/test' } diff --git a/crates/backend/Cargo.toml b/crates/backend/Cargo.toml index 4ff518442d9..a19b7812efd 100644 --- a/crates/backend/Cargo.toml +++ b/crates/backend/Cargo.toml @@ -15,6 +15,7 @@ version = "0.2.95" [features] atomics = [] +coverage = [] default = ["std"] extra-traits = ["syn/extra-traits"] spans = [] diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 13349eec53b..2a4f8697b40 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -224,6 +224,7 @@ impl ToTokens for ast::Struct { let free_fn = Ident::new(&shared::free_function(&name_str), Span::call_site()); let unwrap_fn = Ident::new(&shared::unwrap_function(&name_str), Span::call_site()); let wasm_bindgen = &self.wasm_bindgen; + let maybe_no_coverage = coverage(); (quote! { #[automatically_derived] impl #wasm_bindgen::describe::WasmDescribe for #name { @@ -300,7 +301,7 @@ impl ToTokens for ast::Struct { #[doc(hidden)] // `allow_delayed` is whether it's ok to not actually free the `ptr` immediately // if it's still borrowed. - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage pub unsafe extern "C" fn #free_fn(ptr: u32, allow_delayed: u32) { use #wasm_bindgen::__rt::alloc::rc::Rc; @@ -476,6 +477,7 @@ impl ToTokens for ast::StructField { quote! { assert_copy::<#ty>() } }; let maybe_assert_copy = respan(maybe_assert_copy, ty); + let maybe_no_coverage = coverage(); // Split this out so that it isn't affected by `quote_spanned!`. // @@ -496,7 +498,7 @@ impl ToTokens for ast::StructField { const _: () = { #[cfg_attr(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")), no_mangle)] #[doc(hidden)] - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage pub unsafe extern "C" fn #getter(js: u32) -> #wasm_bindgen::convert::WasmRet<<#ty as #wasm_bindgen::convert::IntoWasmAbi>::Abi> { @@ -538,7 +540,7 @@ impl ToTokens for ast::StructField { const _: () = { #[no_mangle] #[doc(hidden)] - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage pub unsafe extern "C" fn #setter( js: u32, #(#args,)* @@ -787,6 +789,8 @@ impl TryToTokens for ast::Export { quote! {} }; + let maybe_no_coverage = coverage(); + (quote! { #[automatically_derived] const _: () = { @@ -795,7 +799,7 @@ impl TryToTokens for ast::Export { all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")), export_name = #export_name, )] - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage pub unsafe extern "C" fn #generated_name(#(#args),*) -> #wasm_bindgen::convert::WasmRet<#projection::Abi> { #start_check @@ -1156,6 +1160,8 @@ impl ToTokens for ast::StringEnum { let hole = variant_count + 1; let attrs = &self.rust_attrs; + let maybe_no_coverage = coverage(); + let invalid_to_str_msg = format!( "Converting an invalid string enum ({}) back to a string is currently not supported", enum_name @@ -1242,7 +1248,7 @@ impl ToTokens for ast::StringEnum { #[automatically_derived] impl #wasm_bindgen::describe::WasmDescribe for #enum_name { - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage fn describe() { use #wasm_bindgen::describe::*; inform(STRING_ENUM); @@ -1541,6 +1547,7 @@ impl ToTokens for ast::Enum { } else { quote! { u32 } }; + let maybe_no_coverage = coverage(); let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; quote! { @@ -1588,7 +1595,7 @@ impl ToTokens for ast::Enum { #[automatically_derived] impl #wasm_bindgen::describe::WasmDescribe for #enum_name { - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage fn describe() { use #wasm_bindgen::describe::*; inform(ENUM); @@ -1853,6 +1860,8 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> { return; } + let maybe_no_coverage = coverage(); + let name = Ident::new(&format!("__wbindgen_describe_{}", ident), ident.span()); let inner = &self.inner; let attrs = &self.attrs; @@ -1864,7 +1873,7 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> { #(#attrs)* #[no_mangle] #[doc(hidden)] - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #maybe_no_coverage pub extern "C" fn #name() { use #wasm_bindgen::describe::*; // See definition of `link_mem_intrinsics` for what this is doing @@ -1955,3 +1964,10 @@ fn respan(input: TokenStream, span: &dyn ToTokens) -> TokenStream { } new_tokens.into_iter().collect() } + +fn coverage() -> Option { + #[cfg(feature = "coverage")] + return Some(quote! { #[coverage(off)] }); + #[cfg(not(feature = "coverage"))] + None +} diff --git a/crates/macro-support/Cargo.toml b/crates/macro-support/Cargo.toml index ba169d4cb92..61ce9c2b9fc 100644 --- a/crates/macro-support/Cargo.toml +++ b/crates/macro-support/Cargo.toml @@ -15,6 +15,7 @@ version = "0.2.95" [features] atomics = ["wasm-bindgen-backend/atomics"] +coverage = ["wasm-bindgen-backend/coverage"] default = ["std"] extra-traits = ["syn/extra-traits"] spans = ["wasm-bindgen-backend/spans"] diff --git a/crates/macro/Cargo.toml b/crates/macro/Cargo.toml index 23b4554a83c..d2b699ff2aa 100644 --- a/crates/macro/Cargo.toml +++ b/crates/macro/Cargo.toml @@ -18,6 +18,7 @@ proc-macro = true [features] atomics = ["wasm-bindgen-macro-support/atomics"] +coverage = ["wasm-bindgen-macro-support/coverage"] default = ["std"] spans = ["wasm-bindgen-macro-support/spans"] std = ["wasm-bindgen-macro-support/std"] @@ -34,6 +35,3 @@ trybuild = "1.0" wasm-bindgen = { path = "../.." } wasm-bindgen-futures = { path = "../futures" } web-sys = { path = "../web-sys", features = ["Worker"] } - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(wasm_bindgen_unstable_test_coverage)'] } diff --git a/crates/macro/src/lib.rs b/crates/macro/src/lib.rs index ce2229845d7..6dc0cbf1792 100644 --- a/crates/macro/src/lib.rs +++ b/crates/macro/src/lib.rs @@ -1,9 +1,6 @@ #![doc(html_root_url = "https://docs.rs/wasm-bindgen-macro/0.2")] #![cfg_attr( - any( - wasm_bindgen_unstable_test_coverage, - all(not(feature = "std"), feature = "atomics") - ), + any(feature = "coverage", all(not(feature = "std"), feature = "atomics")), feature(allow_internal_unstable), allow(internal_features) )] @@ -14,10 +11,7 @@ use proc_macro::TokenStream; use quote::quote; #[proc_macro_attribute] -#[cfg_attr( - wasm_bindgen_unstable_test_coverage, - allow_internal_unstable(coverage_attribute) -)] +#[cfg_attr(feature = "coverage", allow_internal_unstable(coverage_attribute))] #[cfg_attr( all(not(feature = "std"), feature = "atomics"), allow_internal_unstable(thread_local) @@ -48,10 +42,7 @@ pub fn wasm_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream { /// let worker = Worker::new(&wasm_bindgen::link_to!(module = "/src/worker.js")); /// ``` #[proc_macro] -#[cfg_attr( - wasm_bindgen_unstable_test_coverage, - allow_internal_unstable(coverage_attribute) -)] +#[cfg_attr(feature = "coverage", allow_internal_unstable(coverage_attribute))] pub fn link_to(input: TokenStream) -> TokenStream { match wasm_bindgen_macro_support::expand_link_to(input.into()) { Ok(tokens) => { @@ -68,10 +59,7 @@ pub fn link_to(input: TokenStream) -> TokenStream { } #[proc_macro_attribute] -#[cfg_attr( - wasm_bindgen_unstable_test_coverage, - allow_internal_unstable(coverage_attribute) -)] +#[cfg_attr(feature = "coverage", allow_internal_unstable(coverage_attribute))] pub fn __wasm_bindgen_class_marker(attr: TokenStream, input: TokenStream) -> TokenStream { match wasm_bindgen_macro_support::expand_class_marker(attr.into(), input.into()) { Ok(tokens) => { diff --git a/crates/test-macro/Cargo.toml b/crates/test-macro/Cargo.toml index e79d2a77e04..d43aafe11d8 100644 --- a/crates/test-macro/Cargo.toml +++ b/crates/test-macro/Cargo.toml @@ -12,6 +12,9 @@ version = "0.3.45" [lib] proc-macro = true +[features] +coverage = [] + [dependencies] proc-macro2 = "1.0" quote = "1.0" @@ -26,6 +29,3 @@ syn = { version = "2.0", default-features = false, features = [ tokio = { version = "1", features = ["macros", "rt-multi-thread"] } trybuild = "1.0" wasm-bindgen-test = { path = "../test" } - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(wasm_bindgen_unstable_test_coverage)'] } diff --git a/crates/test-macro/src/lib.rs b/crates/test-macro/src/lib.rs index c18b8ecad8b..3b0f722bc7e 100644 --- a/crates/test-macro/src/lib.rs +++ b/crates/test-macro/src/lib.rs @@ -2,7 +2,7 @@ //! going on here. #![cfg_attr( - wasm_bindgen_unstable_test_coverage, + feature = "coverage", feature(allow_internal_unstable), allow(internal_features) )] @@ -18,10 +18,7 @@ use std::sync::atomic::*; static CNT: AtomicUsize = AtomicUsize::new(0); #[proc_macro_attribute] -#[cfg_attr( - wasm_bindgen_unstable_test_coverage, - allow_internal_unstable(coverage_attribute) -)] +#[cfg_attr(feature = "coverage", allow_internal_unstable(coverage_attribute))] pub fn wasm_bindgen_test( attr: proc_macro::TokenStream, body: proc_macro::TokenStream, @@ -109,12 +106,17 @@ pub fn wasm_bindgen_test( // main test harness. This is the entry point for all tests. let name = format_ident!("__wbgt_{}_{}", ident, CNT.fetch_add(1, Ordering::SeqCst)); let wasm_bindgen_path = attributes.wasm_bindgen_path; + let coverage = if cfg!(feature = "coverage") { + Some(quote! { #[coverage(off)] }) + } else { + None + }; tokens.extend( quote! { const _: () = { #[no_mangle] #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] - #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))] + #coverage pub extern "C" fn #name(cx: &#wasm_bindgen_path::__rt::Context) { let test_name = ::core::concat!(::core::module_path!(), "::", ::core::stringify!(#ident)); #test_body diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index 70c9e2131c8..a25128ffcfb 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -24,6 +24,7 @@ wasm-bindgen-test-macro = { path = '../test-macro', version = '=0.3.45' } [target.'cfg(all(target_arch = "wasm32", wasm_bindgen_unstable_test_coverage))'.dependencies] minicov = "0.3" +wasm-bindgen-test-macro = { path = '../test-macro', version = '=0.3.45', features = ["coverage"] } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(wasm_bindgen_unstable_test_coverage)'] } diff --git a/guide/src/wasm-bindgen-test/coverage.md b/guide/src/wasm-bindgen-test/coverage.md index fb5a9c92d84..4bd3e6722ce 100644 --- a/guide/src/wasm-bindgen-test/coverage.md +++ b/guide/src/wasm-bindgen-test/coverage.md @@ -9,12 +9,7 @@ You can ask the runner to generate coverage data from functions marked as `#[was ## Enabling the feature -To enable this feature, you need to set `cfg(wasm_bindgen_unstable_test_coverage)` for `wasm-bindgen-test` and its dependencies. - -Currently it is particularly difficult to [deliver compile-line arguments to proc-macros when cross-compiling with Cargo][1]. To circumvent this [host-config] can be used. - -[1]: https://github.com/rust-lang/cargo/issues/4423 -[host-config]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#host-config +To enable this feature, you need to enable `cfg(wasm_bindgen_unstable_test_coverage)`. ## Generating the data @@ -26,18 +21,18 @@ Due to the current limitation of `llvm-cov`, we can't collect profiling symbols ### Arguments to the test runner -The following environment variables can be used to control the coverage output when [executing the test runner][2]: +The following environment variables can be used to control the coverage output when [executing the test runner][1]: -- `WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT` to control the file name of the profraw or the directory in which it is placed +- `WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_OUT` to control the file name of the profraw or the directory in which it is placed. It might be necessary to provide the full path if e.g. running tests in a workspace. - `WASM_BINDGEN_UNSTABLE_TEST_PROFRAW_PREFIX` to add a custom prefix to the profraw files. This can be useful if you're running the tests automatically in succession. -[2]: usage.html#appendix-using-wasm-bindgen-test-without-wasm-pack +[1]: usage.html#appendix-using-wasm-bindgen-test-without-wasm-pack ### Target features -This feature relies on the [minicov] crate, which provides a profiling runtime for WebAssembly. It in turn uses [cc] to compile the runtime to Wasm, which [currently doesn't support accounting for target feature][3]. Use e.g. `CFLAGS_wasm32_unknown_unknown="-matomics -mbulk-memory"` to account for that. +This feature relies on the [minicov] crate, which provides a profiling runtime for WebAssembly. It in turn uses [cc] to compile the runtime to Wasm, which [currently doesn't support accounting for target feature][2]. Use e.g. `CFLAGS_wasm32_unknown_unknown="-matomics -mbulk-memory"` to account for that. -[3]: https://github.com/rust-lang/cc-rs/issues/268 +[2]: https://github.com/rust-lang/cc-rs/issues/268 [cc]: https://crates.io/crates/cc [minicov]: https://crates.io/crates/minicov @@ -47,13 +42,10 @@ This adapts code taken from the [Rustc book], see that for more examples and gen ```sh # Run the tests: -# - `CARGO_HOST_RUSTFLAGS` to pass the configuration to `wasm-bindgen-macro`. -# - `-Ztarget-applies-to-host -Zhost-config` to enable `CARGO_HOST_RUSTFLAGS`. -# - `--tests` to not run documentation tests, which is currently not supported. -CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage \ +# `--tests` to not run documentation tests, which is currently not supported. RUSTFLAGS="-Cinstrument-coverage -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage" \ CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner \ -cargo +nightly test -Ztarget-applies-to-host -Zhost-config --tests +cargo +nightly test --tests # Compile to object files: # - Extract a list of compiled artifacts from Cargo and filter them with `jq`. # - Figure out the path to the LLVM IR file corresponding to an artifact. @@ -62,9 +54,8 @@ crate_name=name_of_the_tested_crate_in_snake_case objects=() IFS=$'\n' for file in $( - CARGO_HOST_RUSTFLAGS=--cfg=wasm_bindgen_unstable_test_coverage \ RUSTFLAGS="-Cinstrument-coverage -Zno-profiler-runtime --emit=llvm-ir --cfg=wasm_bindgen_unstable_test_coverage" \ - cargo +nightly test -Ztarget-applies-to-host -Zhost-config --tests --no-run --message-format=json | \ + cargo +nightly test --tests --no-run --message-format=json | \ jq -r "select(.reason == \"compiler-artifact\") | (select(.target.kind == [\"test\"]) // select(.target.name == \"$crate_name\")) | .filenames[0]" ) do @@ -89,7 +80,7 @@ llvm-cov-19 show -show-instantiations=false -Xdemangler=rustfilt -output-dir cov ## Attribution -These methods have originally been pioneered by [Hacken OÜ], see [their guide][4] as well. +These methods have originally been pioneered by [Hacken OÜ], see [their guide][3] as well. -[4]: https://hknio.github.io/wasmcov +[3]: https://hknio.github.io/wasmcov [Hacken OÜ]: https://hacken.io