Skip to content

Commit 578d59e

Browse files
authored
Merge pull request #1440 from c410-f3r/getters
Getters/Setters for fields
2 parents 402e72e + 3031c15 commit 578d59e

File tree

13 files changed

+528
-201
lines changed

13 files changed

+528
-201
lines changed

crates/backend/src/ast.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,18 @@ pub struct Program {
3434
#[cfg_attr(feature = "extra-traits", derive(Debug))]
3535
#[derive(Clone)]
3636
pub struct Export {
37-
/// The struct name, in Rust, this is attached to
38-
pub rust_class: Option<Ident>,
37+
/// Comments extracted from the rust source.
38+
pub comments: Vec<String>,
39+
/// The rust function
40+
pub function: Function,
3941
/// The class name in JS this is attached to
4042
pub js_class: Option<String>,
43+
/// The kind (static, named, regular)
44+
pub method_kind: MethodKind,
4145
/// The type of `self` (either `self`, `&self`, or `&mut self`)
4246
pub method_self: Option<MethodSelf>,
43-
/// Whether or not this export is flagged as a constructor, returning an
44-
/// instance of the `impl` type
45-
pub is_constructor: bool,
46-
/// The rust function
47-
pub function: Function,
48-
/// Comments extracted from the rust source.
49-
pub comments: Vec<String>,
47+
/// The struct name, in Rust, this is attached to
48+
pub rust_class: Option<Ident>,
5049
/// The name of the rust function/method on the rust side.
5150
pub rust_name: Ident,
5251
/// Whether or not this function should be flagged as the wasm start
@@ -342,28 +341,28 @@ impl ImportKind {
342341
}
343342
}
344343

345-
impl ImportFunction {
344+
impl Function {
346345
/// If the rust object has a `fn xxx(&self) -> MyType` method, get the name for a getter in
347346
/// javascript (in this case `xxx`, so you can write `val = obj.xxx`)
348347
pub fn infer_getter_property(&self) -> &str {
349-
&self.function.name
348+
&self.name
350349
}
351350

352351
/// If the rust object has a `fn set_xxx(&mut self, MyType)` style method, get the name
353352
/// for a setter in javascript (in this case `xxx`, so you can write `obj.xxx = val`)
354353
pub fn infer_setter_property(&self) -> Result<String, Diagnostic> {
355-
let name = self.function.name.to_string();
354+
let name = self.name.to_string();
356355

357356
// if `#[wasm_bindgen(js_name = "...")]` is used then that explicitly
358357
// because it was hand-written anyway.
359-
if self.function.renamed_via_js_name {
358+
if self.renamed_via_js_name {
360359
return Ok(name);
361360
}
362361

363362
// Otherwise we infer names based on the Rust function name.
364363
if !name.starts_with("set_") {
365364
bail_span!(
366-
syn::token::Pub(self.function.name_span),
365+
syn::token::Pub(self.name_span),
367366
"setters must start with `set_`, found: {}",
368367
name,
369368
);

crates/backend/src/encode.rs

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn shared_program<'a>(
125125
.exports
126126
.iter()
127127
.map(|a| shared_export(a, intern))
128-
.collect(),
128+
.collect::<Result<Vec<_>, _>>()?,
129129
structs: prog
130130
.structs
131131
.iter()
@@ -172,21 +172,23 @@ fn shared_program<'a>(
172172
})
173173
}
174174

175-
fn shared_export<'a>(export: &'a ast::Export, intern: &'a Interner) -> Export<'a> {
176-
let (method, consumed) = match export.method_self {
177-
Some(ast::MethodSelf::ByValue) => (true, true),
178-
Some(_) => (true, false),
179-
None => (false, false),
175+
fn shared_export<'a>(
176+
export: &'a ast::Export,
177+
intern: &'a Interner,
178+
) -> Result<Export<'a>, Diagnostic> {
179+
let consumed = match export.method_self {
180+
Some(ast::MethodSelf::ByValue) => true,
181+
_ => false,
180182
};
181-
Export {
183+
let method_kind = from_ast_method_kind(&export.function, intern, &export.method_kind)?;
184+
Ok(Export {
182185
class: export.js_class.as_ref().map(|s| &**s),
183-
method,
186+
comments: export.comments.iter().map(|s| &**s).collect(),
184187
consumed,
185-
is_constructor: export.is_constructor,
186188
function: shared_function(&export.function, intern),
187-
comments: export.comments.iter().map(|s| &**s).collect(),
189+
method_kind,
188190
start: export.start,
189-
}
191+
})
190192
}
191193

192194
fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Function<'a> {
@@ -203,8 +205,8 @@ fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Functi
203205
})
204206
.collect::<Vec<_>>();
205207
Function {
206-
name: &func.name,
207208
arg_names,
209+
name: &func.name,
208210
}
209211
}
210212

@@ -260,30 +262,7 @@ fn shared_import_function<'a>(
260262
) -> Result<ImportFunction<'a>, Diagnostic> {
261263
let method = match &i.kind {
262264
ast::ImportFunctionKind::Method { class, kind, .. } => {
263-
let kind = match kind {
264-
ast::MethodKind::Constructor => MethodKind::Constructor,
265-
ast::MethodKind::Operation(ast::Operation { is_static, kind }) => {
266-
let is_static = *is_static;
267-
let kind = match kind {
268-
ast::OperationKind::Regular => OperationKind::Regular,
269-
ast::OperationKind::Getter(g) => {
270-
let g = g.as_ref().map(|g| intern.intern(g));
271-
OperationKind::Getter(g.unwrap_or_else(|| i.infer_getter_property()))
272-
}
273-
ast::OperationKind::Setter(s) => {
274-
let s = s.as_ref().map(|s| intern.intern(s));
275-
OperationKind::Setter(match s {
276-
Some(s) => s,
277-
None => intern.intern_str(&i.infer_setter_property()?),
278-
})
279-
}
280-
ast::OperationKind::IndexingGetter => OperationKind::IndexingGetter,
281-
ast::OperationKind::IndexingSetter => OperationKind::IndexingSetter,
282-
ast::OperationKind::IndexingDeleter => OperationKind::IndexingDeleter,
283-
};
284-
MethodKind::Operation(Operation { is_static, kind })
285-
}
286-
};
265+
let kind = from_ast_method_kind(&i.function, intern, kind)?;
287266
Some(MethodData { class, kind })
288267
}
289268
ast::ImportFunctionKind::Normal => None,
@@ -510,3 +489,34 @@ macro_rules! encode_api {
510489
);
511490
}
512491
wasm_bindgen_shared::shared_api!(encode_api);
492+
493+
fn from_ast_method_kind<'a>(
494+
function: &'a ast::Function,
495+
intern: &'a Interner,
496+
method_kind: &'a ast::MethodKind,
497+
) -> Result<MethodKind<'a>, Diagnostic> {
498+
Ok(match method_kind {
499+
ast::MethodKind::Constructor => MethodKind::Constructor,
500+
ast::MethodKind::Operation(ast::Operation { is_static, kind }) => {
501+
let is_static = *is_static;
502+
let kind = match kind {
503+
ast::OperationKind::Getter(g) => {
504+
let g = g.as_ref().map(|g| intern.intern(g));
505+
OperationKind::Getter(g.unwrap_or_else(|| function.infer_getter_property()))
506+
}
507+
ast::OperationKind::Regular => OperationKind::Regular,
508+
ast::OperationKind::Setter(s) => {
509+
let s = s.as_ref().map(|s| intern.intern(s));
510+
OperationKind::Setter(match s {
511+
Some(s) => s,
512+
None => intern.intern_str(&function.infer_setter_property()?),
513+
})
514+
}
515+
ast::OperationKind::IndexingGetter => OperationKind::IndexingGetter,
516+
ast::OperationKind::IndexingSetter => OperationKind::IndexingSetter,
517+
ast::OperationKind::IndexingDeleter => OperationKind::IndexingDeleter,
518+
};
519+
MethodKind::Operation(Operation { is_static, kind })
520+
}
521+
})
522+
}

crates/cli-support/src/js/js2rust.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,24 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
103103

104104
/// Flag this shim as a method call into Rust, so the first Rust argument
105105
/// passed should be `this.ptr`.
106-
pub fn method(&mut self, method: bool, consumed: bool) -> &mut Self {
107-
if method {
108-
if self.cx.config.debug {
109-
self.prelude(
110-
"if (this.ptr === 0) {
111-
throw new Error('Attempt to use a moved value');
112-
}",
113-
);
114-
}
115-
if consumed {
116-
self.prelude(
117-
"\
118-
const ptr = this.ptr;\n\
119-
this.ptr = 0;\n\
120-
",
121-
);
122-
self.rust_arguments.insert(0, "ptr".to_string());
123-
} else {
124-
self.rust_arguments.insert(0, "this.ptr".to_string());
125-
}
106+
pub fn method(&mut self, consumed: bool) -> &mut Self {
107+
if self.cx.config.debug {
108+
self.prelude(
109+
"if (this.ptr === 0) {
110+
throw new Error('Attempt to use a moved value');
111+
}",
112+
);
113+
}
114+
if consumed {
115+
self.prelude(
116+
"\
117+
const ptr = this.ptr;\n\
118+
this.ptr = 0;\n\
119+
",
120+
);
121+
self.rust_arguments.insert(0, "ptr".to_string());
122+
} else {
123+
self.rust_arguments.insert(0, "this.ptr".to_string());
126124
}
127125
self
128126
}

0 commit comments

Comments
 (0)