mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-12 12:31:22 +00:00
Merge pull request #1440 from c410-f3r/getters
Getters/Setters for fields
This commit is contained in:
@ -34,19 +34,18 @@ pub struct Program {
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
||||
#[derive(Clone)]
|
||||
pub struct Export {
|
||||
/// The struct name, in Rust, this is attached to
|
||||
pub rust_class: Option<Ident>,
|
||||
/// The class name in JS this is attached to
|
||||
pub js_class: Option<String>,
|
||||
/// The type of `self` (either `self`, `&self`, or `&mut self`)
|
||||
pub method_self: Option<MethodSelf>,
|
||||
/// Whether or not this export is flagged as a constructor, returning an
|
||||
/// instance of the `impl` type
|
||||
pub is_constructor: bool,
|
||||
/// The rust function
|
||||
pub function: Function,
|
||||
/// Comments extracted from the rust source.
|
||||
pub comments: Vec<String>,
|
||||
/// The rust function
|
||||
pub function: Function,
|
||||
/// The class name in JS this is attached to
|
||||
pub js_class: Option<String>,
|
||||
/// The kind (static, named, regular)
|
||||
pub method_kind: MethodKind,
|
||||
/// The type of `self` (either `self`, `&self`, or `&mut self`)
|
||||
pub method_self: Option<MethodSelf>,
|
||||
/// The struct name, in Rust, this is attached to
|
||||
pub rust_class: Option<Ident>,
|
||||
/// The name of the rust function/method on the rust side.
|
||||
pub rust_name: Ident,
|
||||
/// Whether or not this function should be flagged as the wasm start
|
||||
@ -342,28 +341,28 @@ impl ImportKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportFunction {
|
||||
impl Function {
|
||||
/// If the rust object has a `fn xxx(&self) -> MyType` method, get the name for a getter in
|
||||
/// javascript (in this case `xxx`, so you can write `val = obj.xxx`)
|
||||
pub fn infer_getter_property(&self) -> &str {
|
||||
&self.function.name
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// If the rust object has a `fn set_xxx(&mut self, MyType)` style method, get the name
|
||||
/// for a setter in javascript (in this case `xxx`, so you can write `obj.xxx = val`)
|
||||
pub fn infer_setter_property(&self) -> Result<String, Diagnostic> {
|
||||
let name = self.function.name.to_string();
|
||||
let name = self.name.to_string();
|
||||
|
||||
// if `#[wasm_bindgen(js_name = "...")]` is used then that explicitly
|
||||
// because it was hand-written anyway.
|
||||
if self.function.renamed_via_js_name {
|
||||
if self.renamed_via_js_name {
|
||||
return Ok(name);
|
||||
}
|
||||
|
||||
// Otherwise we infer names based on the Rust function name.
|
||||
if !name.starts_with("set_") {
|
||||
bail_span!(
|
||||
syn::token::Pub(self.function.name_span),
|
||||
syn::token::Pub(self.name_span),
|
||||
"setters must start with `set_`, found: {}",
|
||||
name,
|
||||
);
|
||||
|
@ -125,7 +125,7 @@ fn shared_program<'a>(
|
||||
.exports
|
||||
.iter()
|
||||
.map(|a| shared_export(a, intern))
|
||||
.collect(),
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
structs: prog
|
||||
.structs
|
||||
.iter()
|
||||
@ -172,21 +172,23 @@ fn shared_program<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
fn shared_export<'a>(export: &'a ast::Export, intern: &'a Interner) -> Export<'a> {
|
||||
let (method, consumed) = match export.method_self {
|
||||
Some(ast::MethodSelf::ByValue) => (true, true),
|
||||
Some(_) => (true, false),
|
||||
None => (false, false),
|
||||
fn shared_export<'a>(
|
||||
export: &'a ast::Export,
|
||||
intern: &'a Interner,
|
||||
) -> Result<Export<'a>, Diagnostic> {
|
||||
let consumed = match export.method_self {
|
||||
Some(ast::MethodSelf::ByValue) => true,
|
||||
_ => false,
|
||||
};
|
||||
Export {
|
||||
let method_kind = from_ast_method_kind(&export.function, intern, &export.method_kind)?;
|
||||
Ok(Export {
|
||||
class: export.js_class.as_ref().map(|s| &**s),
|
||||
method,
|
||||
consumed,
|
||||
is_constructor: export.is_constructor,
|
||||
function: shared_function(&export.function, intern),
|
||||
comments: export.comments.iter().map(|s| &**s).collect(),
|
||||
consumed,
|
||||
function: shared_function(&export.function, intern),
|
||||
method_kind,
|
||||
start: export.start,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Function {
|
||||
name: &func.name,
|
||||
arg_names,
|
||||
name: &func.name,
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,30 +262,7 @@ fn shared_import_function<'a>(
|
||||
) -> Result<ImportFunction<'a>, Diagnostic> {
|
||||
let method = match &i.kind {
|
||||
ast::ImportFunctionKind::Method { class, kind, .. } => {
|
||||
let kind = match kind {
|
||||
ast::MethodKind::Constructor => MethodKind::Constructor,
|
||||
ast::MethodKind::Operation(ast::Operation { is_static, kind }) => {
|
||||
let is_static = *is_static;
|
||||
let kind = match kind {
|
||||
ast::OperationKind::Regular => OperationKind::Regular,
|
||||
ast::OperationKind::Getter(g) => {
|
||||
let g = g.as_ref().map(|g| intern.intern(g));
|
||||
OperationKind::Getter(g.unwrap_or_else(|| i.infer_getter_property()))
|
||||
}
|
||||
ast::OperationKind::Setter(s) => {
|
||||
let s = s.as_ref().map(|s| intern.intern(s));
|
||||
OperationKind::Setter(match s {
|
||||
Some(s) => s,
|
||||
None => intern.intern_str(&i.infer_setter_property()?),
|
||||
})
|
||||
}
|
||||
ast::OperationKind::IndexingGetter => OperationKind::IndexingGetter,
|
||||
ast::OperationKind::IndexingSetter => OperationKind::IndexingSetter,
|
||||
ast::OperationKind::IndexingDeleter => OperationKind::IndexingDeleter,
|
||||
};
|
||||
MethodKind::Operation(Operation { is_static, kind })
|
||||
}
|
||||
};
|
||||
let kind = from_ast_method_kind(&i.function, intern, kind)?;
|
||||
Some(MethodData { class, kind })
|
||||
}
|
||||
ast::ImportFunctionKind::Normal => None,
|
||||
@ -510,3 +489,34 @@ macro_rules! encode_api {
|
||||
);
|
||||
}
|
||||
wasm_bindgen_shared::shared_api!(encode_api);
|
||||
|
||||
fn from_ast_method_kind<'a>(
|
||||
function: &'a ast::Function,
|
||||
intern: &'a Interner,
|
||||
method_kind: &'a ast::MethodKind,
|
||||
) -> Result<MethodKind<'a>, Diagnostic> {
|
||||
Ok(match method_kind {
|
||||
ast::MethodKind::Constructor => MethodKind::Constructor,
|
||||
ast::MethodKind::Operation(ast::Operation { is_static, kind }) => {
|
||||
let is_static = *is_static;
|
||||
let kind = match kind {
|
||||
ast::OperationKind::Getter(g) => {
|
||||
let g = g.as_ref().map(|g| intern.intern(g));
|
||||
OperationKind::Getter(g.unwrap_or_else(|| function.infer_getter_property()))
|
||||
}
|
||||
ast::OperationKind::Regular => OperationKind::Regular,
|
||||
ast::OperationKind::Setter(s) => {
|
||||
let s = s.as_ref().map(|s| intern.intern(s));
|
||||
OperationKind::Setter(match s {
|
||||
Some(s) => s,
|
||||
None => intern.intern_str(&function.infer_setter_property()?),
|
||||
})
|
||||
}
|
||||
ast::OperationKind::IndexingGetter => OperationKind::IndexingGetter,
|
||||
ast::OperationKind::IndexingSetter => OperationKind::IndexingSetter,
|
||||
ast::OperationKind::IndexingDeleter => OperationKind::IndexingDeleter,
|
||||
};
|
||||
MethodKind::Operation(Operation { is_static, kind })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user