Skip to content

Commit

Permalink
Merge pull request #1577 from c410-f3r/getters-setters-ts
Browse files Browse the repository at this point in the history
Fix getter and setter for TS
  • Loading branch information
alexcrichton authored Jun 7, 2019
2 parents cf2a42c + e7e8ae1 commit 96d333a
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 22 deletions.
57 changes: 35 additions & 22 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,15 +601,16 @@ impl<'a> Context<'a> {
},
wasm_bindgen_shared::free_function(&name),
));
ts_dst.push_str(" free(): void;");
ts_dst.push_str(" free(): void;\n");
dst.push_str(&class.contents);
ts_dst.push_str(&class.typescript);

let mut fields = class.typescript_fields.keys().collect::<Vec<_>>();
fields.sort(); // make sure we have deterministic output
for name in fields {
let (ty, readonly) = &class.typescript_fields[name];
if *readonly {
let (ty, has_setter) = &class.typescript_fields[name];
ts_dst.push_str(" ");
if !has_setter {
ts_dst.push_str("readonly ");
}
ts_dst.push_str(name);
Expand Down Expand Up @@ -1890,20 +1891,24 @@ impl<'a> Context<'a> {
let (js, ts, raw_docs) = j2r
.process(&descriptor, &export.arg_names)?
.finish("", &format!("wasm.{}", wasm_name));
let ret_ty = j2r.ret_ty.clone();
let exported = require_class(&mut self.exported_classes, class);
let docs = format_doc_comments(&export.comments, Some(raw_docs));
match export.kind {
AuxExportKind::Getter { .. } => {
exported.push_field(&docs, name, &js, Some(&ret_ty), true);
let ret_ty = j2r.ret_ty.clone();
let exported = require_class(&mut self.exported_classes, class);
exported.push_getter(&docs, name, &js, &ret_ty);
}
AuxExportKind::Setter { .. } => {
exported.push_field(&docs, name, &js, None, false);
let arg_ty = &j2r.js_arguments[0].type_.clone();
let exported = require_class(&mut self.exported_classes, class);
exported.push_setter(&docs, name, &js, &arg_ty);
}
AuxExportKind::StaticFunction { .. } => {
let exported = require_class(&mut self.exported_classes, class);
exported.push(&docs, name, "static ", &js, &ts);
}
_ => {
let exported = require_class(&mut self.exported_classes, class);
exported.push(&docs, name, "", &js, &ts);
}
}
Expand Down Expand Up @@ -2155,30 +2160,38 @@ impl ExportedClass {
self.typescript.push_str("\n");
}

/// Used for adding a field to a class, mainly to ensure that TypeScript
/// Used for adding a getter to a class, mainly to ensure that TypeScript
/// generation is handled specially.
///
/// Note that the `ts` is optional and it's expected to just be the field
/// type, not the full signature. It's currently only available on getters,
/// but there currently has to always be at least a getter.
fn push_field(&mut self, docs: &str, field: &str, js: &str, ts: Option<&str>, getter: bool) {
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: &str) {
self.push_accessor(docs, field, js, "get ", ret_ty);
}

/// Used for adding a setter to a class, mainly to ensure that TypeScript
/// generation is handled specially.
fn push_setter(&mut self, docs: &str, field: &str, js: &str, ret_ty: &str) {
let has_setter = self.push_accessor(docs, field, js, "set ", ret_ty);
*has_setter = true;
}

fn push_accessor(
&mut self,
docs: &str,
field: &str,
js: &str,
prefix: &str,
ret_ty: &str
) -> &mut bool {
self.contents.push_str(docs);
if getter {
self.contents.push_str("get ");
} else {
self.contents.push_str("set ");
}
self.contents.push_str(prefix);
self.contents.push_str(field);
self.contents.push_str(js);
self.contents.push_str("\n");
let (ty, has_setter) = self
.typescript_fields
.entry(field.to_string())
.or_insert_with(Default::default);
if let Some(ts) = ts {
*ty = ts.to_string();
}
*has_setter = *has_setter || !getter;
*ty = ret_ty.to_string();
has_setter
}
}

Expand Down
57 changes: 57 additions & 0 deletions crates/typescript-tests/src/getters_setters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct ColorWithGetter { r: f64, _g: f64, _b: f64, _a: u8 }

#[wasm_bindgen]
impl ColorWithGetter {
#[wasm_bindgen(getter)]
pub fn r(&self) -> f64 {
self.r
}
}

#[wasm_bindgen]
pub struct ColorWithSetter { r: f64, _g: f64, _b: f64, a: u8 }

#[wasm_bindgen]
impl ColorWithSetter {
#[wasm_bindgen(setter)]
pub fn set_r(&mut self, r: f64) {
self.r = r;
self.a = if self.r > 1.0 {
255
}
else if self.r < 0.0 {
0
}
else {
(self.r * 255.0) as u8
};
}
}

#[wasm_bindgen]
pub struct ColorWithGetterAndSetter { r: f64, _g: f64, _b: f64, a: u8 }

#[wasm_bindgen]
impl ColorWithGetterAndSetter {
#[wasm_bindgen(getter)]
pub fn r(&self) -> f64 {
self.r
}

#[wasm_bindgen(setter)]
pub fn set_r(&mut self, r: f64) {
self.r = r;
self.a = if self.r > 1.0 {
255
}
else if self.r < 0.0 {
0
}
else {
(self.r * 255.0) as u8
};
}
}
11 changes: 11 additions & 0 deletions crates/typescript-tests/src/getters_setters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as wbg from '../pkg/typescript_tests';

const colorWithGetter: wbg.ColorWithGetter = new wbg.ColorWithGetter;
const _a = colorWithGetter.r;

const colorWithSetter: wbg.ColorWithSetter = new wbg.ColorWithSetter;
colorWithSetter.r = 1;

const colorWithGetterAndSetter: wbg.ColorWithGetterAndSetter = new wbg.ColorWithGetterAndSetter;
colorWithGetterAndSetter.r = 1;
const _b = colorWithGetterAndSetter.r;
1 change: 1 addition & 0 deletions crates/typescript-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod custom_section;
mod getters_setters;
mod opt_args_and_ret;
mod simple_fn;
mod simple_struct;

0 comments on commit 96d333a

Please sign in to comment.