Allow specifying getter/setter properties

Should help with style clashes!
This commit is contained in:
Alex Crichton 2018-03-22 18:21:41 -07:00
parent 78e3537279
commit 30936a6b22
4 changed files with 107 additions and 16 deletions

View File

@ -975,6 +975,22 @@ possibilities!
accessible as `foo.set_property(2)`. Note that both functions have a `this`
argument as they're tagged with `method`.
Finally, you can also pass a string argument to the `getter` and `setter`
properties to configure what property is accessed. When the property is
explicitly specified then there is no restriction on the method name. For
example the below is equivalent to the above:
```rust
#[wasm_bindgen]
extern {
type Foo;
#[wasm_bindgen(method, getter = "property")]
fn assorted_method_name(this: &Foo) -> u32;
#[wasm_bindgen(method, setter = "property")]
fn some_other_method_name(this: &Foo, val: u32);
}
```
Properties in JS are accessed through `Object.getOwnPropertyDescriptor`. Note
that this typically only works for class-like-defined properties which aren't
just attached properties on any old object. For accessing any old property on

View File

@ -651,24 +651,26 @@ impl BindgenAttrs {
.next()
}
pub fn getter(&self) -> bool {
pub fn getter(&self) -> Option<Option<String>> {
self.attrs.iter()
.any(|a| {
.filter_map(|a| {
match *a {
BindgenAttr::Getter => true,
_ => false,
BindgenAttr::Getter(ref s) => Some(s.clone()),
_ => None,
}
})
.next()
}
pub fn setter(&self) -> bool {
pub fn setter(&self) -> Option<Option<String>> {
self.attrs.iter()
.any(|a| {
.filter_map(|a| {
match *a {
BindgenAttr::Setter => true,
_ => false,
BindgenAttr::Setter(ref s) => Some(s.clone()),
_ => None,
}
})
.next()
}
pub fn structural(&self) -> bool {
@ -703,8 +705,8 @@ enum BindgenAttr {
Method,
JsNamespace(syn::Ident),
Module(String),
Getter,
Setter,
Getter(Option<String>),
Setter(Option<String>),
Structural,
}
@ -716,9 +718,25 @@ impl syn::synom::Synom for BindgenAttr {
|
call!(term, "method") => { |_| BindgenAttr::Method }
|
call!(term, "getter") => { |_| BindgenAttr::Getter }
do_parse!(
call!(term, "getter") >>
val: option!(do_parse!(
punct!(=) >>
s: syn!(syn::LitStr) >>
(s.value())
)) >>
(val)
)=> { BindgenAttr::Getter }
|
call!(term, "setter") => { |_| BindgenAttr::Setter }
do_parse!(
call!(term, "setter") >>
val: option!(do_parse!(
punct!(=) >>
s: syn!(syn::LitStr) >>
(s.value())
)) >>
(val)
)=> { BindgenAttr::Setter }
|
call!(term, "structural") => { |_| BindgenAttr::Structural }
|

View File

@ -244,11 +244,11 @@ impl Literal for ast::ImportFunction {
let mut setter = None;
let structural = self.function.opts.structural();
if self.function.opts.getter() {
getter = Some(self.infer_getter_property());
if let Some(s) = self.function.opts.getter() {
getter = Some(s.unwrap_or_else(|| self.infer_getter_property()));
}
if self.function.opts.setter() {
setter = Some(self.infer_setter_property());
if let Some(s) = self.function.opts.setter() {
setter = Some(s.unwrap_or_else(|| self.infer_setter_property()));
}
a.fields(&[
("kind", &|a| a.str("function")),

View File

@ -335,3 +335,60 @@ fn properties() {
"#)
.test();
}
#[test]
fn rename_setter_getter() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./another")]
extern {
type Foo;
#[wasm_bindgen(constructor)]
fn new() -> Foo;
#[wasm_bindgen(getter = "a", method)]
fn test(this: &Foo) -> i32;
#[wasm_bindgen(setter = "a", method)]
fn another(this: &Foo, a: i32);
}
#[wasm_bindgen]
pub fn run() {
let a = Foo::new();
assert_eq!(a.test(), 1);
a.another(2);
assert_eq!(a.test(), 2);
}
"#)
.file("test.ts", r#"
import { run } from "./out";
export function test() {
run();
}
"#)
.file("another.ts", r#"
export class Foo {
constructor(private num: number) {
this.num = 1;
}
get a() {
return this.num;
}
set a(val) {
this.num = val;
}
}
"#)
.test();
}