Skip to main content

wry_bindgen_macro_support/
lib.rs

1//! wry-bindgen-macro-support - Implementation of the wasm_bindgen attribute macro
2//!
3//! This crate contains Wry code generation for the `#[wasm_bindgen]`
4//! attribute macro. Parsing and macro API compatibility come from upstream
5//! `wasm-bindgen-macro-support`.
6
7mod codegen;
8
9use proc_macro2::TokenStream;
10use quote::quote;
11use wasm_bindgen_macro_support::Diagnostic;
12
13/// Expand the wasm_bindgen attribute macro.
14///
15/// This is the main entry point called by the proc-macro crate.
16pub fn expand(attr: TokenStream, input: TokenStream) -> Result<TokenStream, Diagnostic> {
17    let program = wasm_bindgen_macro_support::parse_with_tokens(attr, input)?;
18    Ok(codegen::generate(&program)?)
19}
20
21/// One `kind = "literal"` argument to `link_to!` (e.g. `module = "./worker.js"`).
22struct LinkToArg {
23    kind: syn::Ident,
24    value: syn::LitStr,
25}
26
27impl syn::parse::Parse for LinkToArg {
28    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
29        let kind: syn::Ident = input.parse()?;
30        let _: syn::Token![=] = input.parse()?;
31        let value: syn::LitStr = input.parse()?;
32        Ok(Self { kind, value })
33    }
34}
35
36/// Expand a `link_to!(kind = "literal")` invocation into a runtime call that
37/// registers the referenced JS with the wry runtime and returns the URL the
38/// WebView serves it from.
39///
40/// - `module`: `include_str!` the source-relative file and register its content.
41/// - `inline_js`: register the literal `&'static str` directly.
42/// - `raw_module`: resolve the opaque specifier verbatim.
43///
44/// The generated calls route through `::wasm_bindgen::__rt`, mirroring how
45/// `#[wasm_bindgen]`-generated module specs reference the runtime.
46pub fn expand_link_to(input: TokenStream) -> Result<TokenStream, Diagnostic> {
47    let LinkToArg { kind, value } = syn::parse2(input).map_err(Diagnostic::from)?;
48    let expanded = match kind.to_string().as_str() {
49        // `include_str!` resolves relative to the call site's source file, so the
50        // included content matches what `register_linked_module` hashes.
51        "module" => quote! {
52            { ::wasm_bindgen::__rt::register_linked_module(include_str!(#value)) }
53        },
54        "inline_js" => quote! {
55            { ::wasm_bindgen::__rt::register_linked_module(#value) }
56        },
57        "raw_module" => quote! {
58            { ::wasm_bindgen::__rt::link_to_raw_specifier(#value) }
59        },
60        other => {
61            return Err(syn::Error::new(
62                kind.span(),
63                format!(
64                    "unsupported `link_to!` argument `{other}`; expected `module`, `raw_module`, or `inline_js`"
65                ),
66            )
67            .into());
68        }
69    };
70    Ok(expanded)
71}
72
73/// Expand an internal wasm-bindgen class marker method.
74pub fn expand_class_marker(
75    attr: TokenStream,
76    input: TokenStream,
77) -> Result<TokenStream, Diagnostic> {
78    let program = wasm_bindgen_macro_support::parse_class_marker_with_tokens(attr, input)?;
79    Ok(codegen::generate(&program)?)
80}