Skip to content

Commit

Permalink
Make getters, setters, and constructors compiler errors for enu…
Browse files Browse the repository at this point in the history
…ms (#4278)
  • Loading branch information
RunDevelopment authored Dec 9, 2024
1 parent af7c106 commit 83a2ff4
Show file tree
Hide file tree
Showing 16 changed files with 406 additions and 15 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update --no-self-update 1.76.0 && rustup default 1.76.0
- run: rustup update --no-self-update 1.78.0 && rustup default 1.78.0
- run: cargo test -p wasm-bindgen-macro
- run: cargo test -p wasm-bindgen-test-macro

Expand Down Expand Up @@ -569,6 +569,8 @@ jobs:
- wasm32-unknown-unknown
features:
- --no-default-features
- --no-default-features --features std
- --no-default-features --features msrv
- ""
defaults:
run:
Expand All @@ -594,6 +596,8 @@ jobs:
- wasm32-unknown-unknown
features:
- --no-default-features
- --no-default-features --features std
- --no-default-features --features msrv
- ""
defaults:
run:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior.
[#4188](https://github.com/rustwasm/wasm-bindgen/pull/4188)

* Adding `getter`, `setter`, and `constructor` methods to enums now results in a compiler error. This was previously erroneously allowed and resulted in invalid JS code gen.
[#4278](https://github.com/rustwasm/wasm-bindgen/pull/4278)

### Fixed

- Fixed using [JavaScript keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords) as identifiers not being handled correctly.
Expand Down
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ features = ["serde-serialize"]
test = false

[features]
default = ["std"]
default = ["std", "msrv"]
enable-interning = ["std"]
serde-serialize = ["serde", "serde_json", "std"]
spans = []
std = ["wasm-bindgen-macro/std", "once_cell/std"]

# Opt-in for Rust language features that require a higher MSRV.
#
# The current rustc version is detected at compile-time, so enabling this
# feature for older compilers will NOT result in a compilation error. Instead,
# any unsupported language feature will not be used.
msrv = ["rustversion"]

# Whether or not the `#[wasm_bindgen]` macro is strict and generates an error on
# all unused attributes
strict-macro = ["wasm-bindgen-macro/strict-macro"]
Expand All @@ -43,6 +50,7 @@ xxx_debug_only_print_generated_code = ["wasm-bindgen-macro/xxx_debug_only_print_
[dependencies]
cfg-if = "1.0.0"
once_cell = { version = "1.12", default-features = false }
rustversion = { version = "1.0", optional = true }
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.99", default-features = false }
Expand Down
48 changes: 43 additions & 5 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ impl ToTokens for ast::Struct {
let unwrap_fn = Ident::new(&shared::unwrap_function(&name_str), Span::call_site());
let wasm_bindgen = &self.wasm_bindgen;
(quote! {
#[automatically_derived]
impl #wasm_bindgen::__rt::marker::SupportsConstructor for #name {}
#[automatically_derived]
impl #wasm_bindgen::__rt::marker::SupportsInstanceProperty for #name {}
#[automatically_derived]
impl #wasm_bindgen::__rt::marker::SupportsStaticProperty for #name {}

#[automatically_derived]
impl #wasm_bindgen::describe::WasmDescribe for #name {
fn describe() {
Expand Down Expand Up @@ -782,12 +789,41 @@ impl TryToTokens for ast::Export {
let nargs = self.function.arguments.len() as u32;
let attrs = &self.function.rust_attrs;

let start_check = if self.start {
quote! { const _ASSERT: fn() = || -> #projection::Abi { loop {} }; }
} else {
quote! {}
let mut checks = Vec::new();
if self.start {
checks.push(quote! { const _ASSERT: fn() = || -> #projection::Abi { loop {} }; });
};

if let Some(class) = self.rust_class.as_ref() {
// little helper function to make sure the check points to the
// location of the function causing the assert to fail
let mut add_check = |token_stream| {
checks.push(respan(token_stream, &self.rust_name));
};

match &self.method_kind {
ast::MethodKind::Constructor => {
add_check(quote! {
let _: #wasm_bindgen::__rt::marker::CheckSupportsConstructor<#class>;
});
}
ast::MethodKind::Operation(operation) => match operation.kind {
ast::OperationKind::Getter(_) | ast::OperationKind::Setter(_) => {
if operation.is_static {
add_check(quote! {
let _: #wasm_bindgen::__rt::marker::CheckSupportsStaticProperty<#class>;
});
} else {
add_check(quote! {
let _: #wasm_bindgen::__rt::marker::CheckSupportsInstanceProperty<#class>;
});
}
}
_ => {}
},
}
}

(quote! {
#[automatically_derived]
const _: () = {
Expand All @@ -798,7 +834,9 @@ impl TryToTokens for ast::Export {
export_name = #export_name,
)]
pub unsafe extern "C" fn #generated_name(#(#args),*) -> #wasm_bindgen::convert::WasmRet<#projection::Abi> {
#start_check
const _: () = {
#(#checks)*
};

let #ret = #call;
#convert_ret
Expand Down
2 changes: 1 addition & 1 deletion crates/macro/ui-tests/async-errors.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ error[E0277]: the trait bound `wasm_bindgen::JsValue: From<BadType>` is not sati
--> ui-tests/async-errors.rs:35:24
|
35 | pub async fn bad3() -> BadType { loop {} }
| ^^^^^^^ the trait `From<BadType>` is not implemented for `wasm_bindgen::JsValue`
| ^^^^^^^ the trait `From<BadType>` is not implemented for `wasm_bindgen::JsValue`, which is required by `BadType: IntoJsResult`
|
= help: the following other types implement trait `From<T>`:
<wasm_bindgen::JsValue as From<bool>>
Expand Down
2 changes: 1 addition & 1 deletion crates/macro/ui-tests/main-debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn main() -> Result<(), Test> {
struct Test;

impl fmt::Debug for Test {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
unimplemented!()
}
}
Expand Down
17 changes: 17 additions & 0 deletions crates/macro/ui-tests/main-infallible.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,20 @@ error: the main function has to be called main
|
10 | fn fail() {}
| ^^^^

warning: unreachable expression
--> ui-tests/main-infallible.rs:4:1
|
4 | #[wasm_bindgen(main)]
| ^^^^^^^^^^^^^^^^^^^^^
| |
| unreachable expression
| any code following this expression is unreachable
|
note: this expression has type `Infallible`, which is uninhabited
--> ui-tests/main-infallible.rs:4:1
|
4 | #[wasm_bindgen(main)]
| ^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(unreachable_code)]` on by default
= note: this warning originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)
35 changes: 35 additions & 0 deletions crates/macro/ui-tests/missing-catch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,38 @@ error[E0277]: the trait bound `Result<wasm_bindgen::JsValue, wasm_bindgen::JsVal
i128
and $N others
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: FromWasmAbi` is not satisfied
--> ui-tests/missing-catch.rs:3:1
|
3 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ the trait `FromWasmAbi` is not implemented for `Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>`
|
= help: the following other types implement trait `FromWasmAbi`:
bool
char
isize
i8
i16
i32
i64
i128
and $N others
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: FromWasmAbi` is not satisfied
--> ui-tests/missing-catch.rs:6:18
|
6 | pub fn foo() -> Result<JsValue, JsValue>;
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromWasmAbi` is not implemented for `Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>`
|
= help: the following other types implement trait `FromWasmAbi`:
bool
char
isize
i8
i16
i32
i64
i128
and $N others
38 changes: 38 additions & 0 deletions crates/macro/ui-tests/traits-not-implemented.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,41 @@ error[E0277]: the trait bound `A: IntoWasmAbi` is not satisfied
i128
and $N others
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `A: IntoWasmAbi` is not satisfied
--> ui-tests/traits-not-implemented.rs:8:19
|
8 | pub fn foo(a: A);
| ^ the trait `IntoWasmAbi` is not implemented for `A`
|
= help: the following other types implement trait `IntoWasmAbi`:
bool
char
isize
i8
i16
i32
i64
i128
and $N others

error[E0277]: the trait bound `A: IntoWasmAbi` is not satisfied
--> ui-tests/traits-not-implemented.rs:8:12
|
5 | #[wasm_bindgen]
| --------------- in this procedural macro expansion
...
8 | pub fn foo(a: A);
| ^^^ the trait `IntoWasmAbi` is not implemented for `A`
|
= help: the following other types implement trait `IntoWasmAbi`:
bool
char
isize
i8
i16
i32
i64
i128
and $N others
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)
82 changes: 82 additions & 0 deletions crates/macro/ui-tests/unsupported-options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct RustStruct {
data: u32,
}

#[wasm_bindgen]
impl RustStruct {
pub fn instance_method(&self) {}
fn priv_instance_method(&self) {}
pub fn static_method() {}

#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self { data: 0 }
}

#[wasm_bindgen(getter)]
pub fn prop(self) -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_prop(self, _value: u32) {}

#[wasm_bindgen(getter)]
pub fn static_prop() -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_static_prop(_value: u32) {}

#[wasm_bindgen(indexing_getter)]
pub fn indexing_getter(self) -> u32 {
32
}
#[wasm_bindgen(indexing_setter)]
pub fn indexing_setter(self, _value: u32) {}
#[wasm_bindgen(indexing_deleter)]
pub fn indexing_deleter(self, _value: u32) {}
}

#[wasm_bindgen]
pub enum RustEnum {
A = 0,
B = 1,
}

#[wasm_bindgen]
impl RustEnum {
pub fn instance_method(self) {}
fn priv_instance_method(self) {}
pub fn static_method() {}

#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self::A
}

#[wasm_bindgen(getter)]
pub fn prop(self) -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_prop(self, _value: u32) {}

#[wasm_bindgen(getter)]
pub fn static_prop() -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_static_prop(_value: u32) {}
}

pub struct NonWasmType;

#[wasm_bindgen]
impl NonWasmType {
pub fn static_method() {}
}

fn main() {}
Loading

0 comments on commit 83a2ff4

Please sign in to comment.