From def914721caf434c0f14fa9eb5df07d07d5113d4 Mon Sep 17 00:00:00 2001 From: Liam Murphy Date: Thu, 30 Nov 2023 07:57:07 +1100 Subject: [PATCH] Remove span in generated field getter (#3725) --- CHANGELOG.md | 5 +++++ crates/backend/src/codegen.rs | 9 ++++++++- tests/wasm/classes.js | 7 +++++++ tests/wasm/classes.rs | 25 +++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9bc727c119..2a246ee6f2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ * Add bindings for `UserActivation`. [#3719](https://github.com/rustwasm/wasm-bindgen/pull/3719) +### Fixed + +* Fixed a compiler error when using `#[wasm_bindgen]` inside `macro_rules!`. + [#3725](https://github.com/rustwasm/wasm-bindgen/pull/3725) + ### Removed * Removed Gecko-only `InstallTriggerData` and Gecko-internal `FlexLineGrowthState`, `GridDeclaration`, `GridTrackState`, diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index bfedcfbc275..bbcbc9cea14 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -389,7 +389,14 @@ impl ToTokens for ast::StructField { }; let maybe_assert_copy = respan(maybe_assert_copy, ty); - let mut val = quote_spanned!(self.rust_name.span()=> (*js).borrow().#rust_name); + // Split this out so that it isn't affected by `quote_spanned!`. + // + // If we don't do this, it might end up being unable to reference `js` + // properly because it doesn't have the same span. + // + // See https://github.com/rustwasm/wasm-bindgen/pull/3725. + let js_token = quote! { js }; + let mut val = quote_spanned!(self.rust_name.span()=> (*#js_token).borrow().#rust_name); if let Some(span) = self.getter_with_clone { val = quote_spanned!(span=> <#ty as Clone>::clone(&#val) ); } diff --git a/tests/wasm/classes.js b/tests/wasm/classes.js index 8e503c65803..49bd4472210 100644 --- a/tests/wasm/classes.js +++ b/tests/wasm/classes.js @@ -241,3 +241,10 @@ exports.js_test_inspectable_classes_can_override_generated_methods = () => { assert.strictEqual(overridden_inspectable.toString(), 'string was overwritten'); overridden_inspectable.free(); }; + +exports.js_test_class_defined_in_macro = () => { + const macroClass = new wasm.InsideMacro(); + assert.strictEqual(macroClass.a, 3); + macroClass.a = 5; + assert.strictEqual(macroClass.a, 5); +}; diff --git a/tests/wasm/classes.rs b/tests/wasm/classes.rs index 9321ff92d7f..6058c0a59da 100644 --- a/tests/wasm/classes.rs +++ b/tests/wasm/classes.rs @@ -34,6 +34,7 @@ extern "C" { fn js_test_option_classes(); fn js_test_inspectable_classes(); fn js_test_inspectable_classes_can_override_generated_methods(); + fn js_test_class_defined_in_macro(); } #[wasm_bindgen_test] @@ -608,3 +609,27 @@ impl OverriddenInspectable { String::from("string was overwritten") } } + +macro_rules! make_struct { + ($field:ident) => { + #[wasm_bindgen] + pub struct InsideMacro { + pub $field: u32, + } + }; +} + +make_struct!(a); + +#[wasm_bindgen] +impl InsideMacro { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + Self { a: 3 } + } +} + +#[wasm_bindgen_test] +fn class_defined_in_macro() { + js_test_class_defined_in_macro(); +}