| 1 | //! A representation of the Abstract Syntax Tree of a Rust program, |
| 2 | //! with all the added metadata necessary to generate Wasm bindings |
| 3 | //! for it. |
| 4 | |
| 5 | use crate::{util::ShortHash, Diagnostic}; |
| 6 | use proc_macro2::{Ident, Span}; |
| 7 | use std::hash::{Hash, Hasher}; |
| 8 | use syn::Path; |
| 9 | use wasm_bindgen_shared as shared; |
| 10 | |
| 11 | /// An abstract syntax tree representing a rust program. Contains |
| 12 | /// extra information for joining up this rust code with javascript. |
| 13 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 14 | #[derive (Clone)] |
| 15 | pub struct Program { |
| 16 | /// rust -> js interfaces |
| 17 | pub exports: Vec<Export>, |
| 18 | /// js -> rust interfaces |
| 19 | pub imports: Vec<Import>, |
| 20 | /// linked-to modules |
| 21 | pub linked_modules: Vec<ImportModule>, |
| 22 | /// rust enums |
| 23 | pub enums: Vec<Enum>, |
| 24 | /// rust structs |
| 25 | pub structs: Vec<Struct>, |
| 26 | /// custom typescript sections to be included in the definition file |
| 27 | pub typescript_custom_sections: Vec<LitOrExpr>, |
| 28 | /// Inline JS snippets |
| 29 | pub inline_js: Vec<String>, |
| 30 | /// Path to wasm_bindgen |
| 31 | pub wasm_bindgen: Path, |
| 32 | /// Path to js_sys |
| 33 | pub js_sys: Path, |
| 34 | /// Path to wasm_bindgen_futures |
| 35 | pub wasm_bindgen_futures: Path, |
| 36 | } |
| 37 | |
| 38 | impl Default for Program { |
| 39 | fn default() -> Self { |
| 40 | Self { |
| 41 | exports: Default::default(), |
| 42 | imports: Default::default(), |
| 43 | linked_modules: Default::default(), |
| 44 | enums: Default::default(), |
| 45 | structs: Default::default(), |
| 46 | typescript_custom_sections: Default::default(), |
| 47 | inline_js: Default::default(), |
| 48 | wasm_bindgen: syn::parse_quote! { wasm_bindgen }, |
| 49 | js_sys: syn::parse_quote! { js_sys }, |
| 50 | wasm_bindgen_futures: syn::parse_quote! { wasm_bindgen_futures }, |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | impl Program { |
| 56 | /// Returns true if the Program is empty |
| 57 | pub fn is_empty(&self) -> bool { |
| 58 | self.exports.is_empty() |
| 59 | && self.imports.is_empty() |
| 60 | && self.enums.is_empty() |
| 61 | && self.structs.is_empty() |
| 62 | && self.typescript_custom_sections.is_empty() |
| 63 | && self.inline_js.is_empty() |
| 64 | } |
| 65 | |
| 66 | /// Name of the link function for a specific linked module |
| 67 | pub fn link_function_name(&self, idx: usize) -> String { |
| 68 | let hash: String = match &self.linked_modules[idx] { |
| 69 | ImportModule::Inline(idx: &usize, _) => ShortHash((1, &self.inline_js[*idx])).to_string(), |
| 70 | other: &ImportModule => ShortHash((0, other)).to_string(), |
| 71 | }; |
| 72 | format!("__wbindgen_link_ {}" , hash) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /// An abstract syntax tree representing a link to a module in Rust. |
| 77 | /// In contrast to Program, LinkToModule must expand to an expression. |
| 78 | /// linked_modules of the inner Program must contain exactly one element |
| 79 | /// whose link is produced by the expression. |
| 80 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 81 | #[derive (Clone)] |
| 82 | pub struct LinkToModule(pub Program); |
| 83 | |
| 84 | /// A rust to js interface. Allows interaction with rust objects/functions |
| 85 | /// from javascript. |
| 86 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 87 | #[derive (Clone)] |
| 88 | pub struct Export { |
| 89 | /// Comments extracted from the rust source. |
| 90 | pub comments: Vec<String>, |
| 91 | /// The rust function |
| 92 | pub function: Function, |
| 93 | /// The class name in JS this is attached to |
| 94 | pub js_class: Option<String>, |
| 95 | /// The kind (static, named, regular) |
| 96 | pub method_kind: MethodKind, |
| 97 | /// The type of `self` (either `self`, `&self`, or `&mut self`) |
| 98 | pub method_self: Option<MethodSelf>, |
| 99 | /// The struct name, in Rust, this is attached to |
| 100 | pub rust_class: Option<Ident>, |
| 101 | /// The name of the rust function/method on the rust side. |
| 102 | pub rust_name: Ident, |
| 103 | /// Whether or not this function should be flagged as the Wasm start |
| 104 | /// function. |
| 105 | pub start: bool, |
| 106 | /// Path to wasm_bindgen |
| 107 | pub wasm_bindgen: Path, |
| 108 | /// Path to wasm_bindgen_futures |
| 109 | pub wasm_bindgen_futures: Path, |
| 110 | } |
| 111 | |
| 112 | /// The 3 types variations of `self`. |
| 113 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 114 | #[derive (Copy, Clone)] |
| 115 | pub enum MethodSelf { |
| 116 | /// `self` |
| 117 | ByValue, |
| 118 | /// `&mut self` |
| 119 | RefMutable, |
| 120 | /// `&self` |
| 121 | RefShared, |
| 122 | } |
| 123 | |
| 124 | /// Things imported from a JS module (in an `extern` block) |
| 125 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 126 | #[derive (Clone)] |
| 127 | pub struct Import { |
| 128 | /// The type of module being imported from, if any |
| 129 | pub module: Option<ImportModule>, |
| 130 | /// The namespace to access the item through, if any |
| 131 | pub js_namespace: Option<Vec<String>>, |
| 132 | /// The type of item being imported |
| 133 | pub kind: ImportKind, |
| 134 | } |
| 135 | |
| 136 | /// The possible types of module to import from |
| 137 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 138 | #[derive (Clone)] |
| 139 | pub enum ImportModule { |
| 140 | /// Import from the named module, with relative paths interpreted |
| 141 | Named(String, Span), |
| 142 | /// Import from the named module, without interpreting paths |
| 143 | RawNamed(String, Span), |
| 144 | /// Import from an inline JS snippet |
| 145 | Inline(usize, Span), |
| 146 | } |
| 147 | |
| 148 | impl Hash for ImportModule { |
| 149 | fn hash<H: Hasher>(&self, h: &mut H) { |
| 150 | match self { |
| 151 | ImportModule::Named(name: &String, _) => (1u8, name).hash(state:h), |
| 152 | ImportModule::Inline(idx: &usize, _) => (2u8, idx).hash(state:h), |
| 153 | ImportModule::RawNamed(name: &String, _) => (3u8, name).hash(state:h), |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | /// The type of item being imported |
| 159 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 160 | #[derive (Clone)] |
| 161 | pub enum ImportKind { |
| 162 | /// Importing a function |
| 163 | Function(ImportFunction), |
| 164 | /// Importing a static value |
| 165 | Static(ImportStatic), |
| 166 | /// Importing a static string |
| 167 | String(ImportString), |
| 168 | /// Importing a type/class |
| 169 | Type(ImportType), |
| 170 | /// Importing a JS enum |
| 171 | Enum(StringEnum), |
| 172 | } |
| 173 | |
| 174 | /// A function being imported from JS |
| 175 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 176 | #[derive (Clone)] |
| 177 | pub struct ImportFunction { |
| 178 | /// The full signature of the function |
| 179 | pub function: Function, |
| 180 | /// The name rust code will use |
| 181 | pub rust_name: Ident, |
| 182 | /// The type being returned |
| 183 | pub js_ret: Option<syn::Type>, |
| 184 | /// Whether to catch JS exceptions |
| 185 | pub catch: bool, |
| 186 | /// Whether the function is variadic on the JS side |
| 187 | pub variadic: bool, |
| 188 | /// Whether the function should use structural type checking |
| 189 | pub structural: bool, |
| 190 | /// Causes the Builder (See cli-support::js::binding::Builder) to error out if |
| 191 | /// it finds itself generating code for a function with this signature |
| 192 | pub assert_no_shim: bool, |
| 193 | /// The kind of function being imported |
| 194 | pub kind: ImportFunctionKind, |
| 195 | /// The shim name to use in the generated code. The 'shim' is a function that appears in |
| 196 | /// the generated JS as a wrapper around the actual function to import, performing any |
| 197 | /// necessary conversions (EG adding a try/catch to change a thrown error into a Result) |
| 198 | pub shim: Ident, |
| 199 | /// The doc comment on this import, if one is provided |
| 200 | pub doc_comment: String, |
| 201 | /// Path to wasm_bindgen |
| 202 | pub wasm_bindgen: Path, |
| 203 | /// Path to wasm_bindgen_futures |
| 204 | pub wasm_bindgen_futures: Path, |
| 205 | } |
| 206 | |
| 207 | /// The type of a function being imported |
| 208 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 209 | #[derive (Clone)] |
| 210 | pub enum ImportFunctionKind { |
| 211 | /// A class method |
| 212 | Method { |
| 213 | /// The name of the class for this method, in JS |
| 214 | class: String, |
| 215 | /// The type of the class for this method, in Rust |
| 216 | ty: syn::Type, |
| 217 | /// The kind of method this is |
| 218 | kind: MethodKind, |
| 219 | }, |
| 220 | /// A standard function |
| 221 | Normal, |
| 222 | } |
| 223 | |
| 224 | /// The type of a method |
| 225 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 226 | #[derive (Clone)] |
| 227 | pub enum MethodKind { |
| 228 | /// A class constructor |
| 229 | Constructor, |
| 230 | /// Any other kind of method |
| 231 | Operation(Operation), |
| 232 | } |
| 233 | |
| 234 | /// The operation performed by a class method |
| 235 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 236 | #[derive (Clone)] |
| 237 | pub struct Operation { |
| 238 | /// Whether this method is static |
| 239 | pub is_static: bool, |
| 240 | /// The internal kind of this Operation |
| 241 | pub kind: OperationKind, |
| 242 | } |
| 243 | |
| 244 | /// The kind of operation performed by a method |
| 245 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 246 | #[derive (Clone)] |
| 247 | pub enum OperationKind { |
| 248 | /// A standard method, nothing special |
| 249 | Regular, |
| 250 | /// A method for getting the value of the provided Ident or String |
| 251 | Getter(Option<String>), |
| 252 | /// A method for setting the value of the provided Ident or String |
| 253 | Setter(Option<String>), |
| 254 | /// A dynamically intercepted getter |
| 255 | IndexingGetter, |
| 256 | /// A dynamically intercepted setter |
| 257 | IndexingSetter, |
| 258 | /// A dynamically intercepted deleter |
| 259 | IndexingDeleter, |
| 260 | } |
| 261 | |
| 262 | /// The type of a static being imported |
| 263 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 264 | #[derive (Clone)] |
| 265 | pub struct ImportStatic { |
| 266 | /// The visibility of this static in Rust |
| 267 | pub vis: syn::Visibility, |
| 268 | /// The type of static being imported |
| 269 | pub ty: syn::Type, |
| 270 | /// The name of the shim function used to access this static |
| 271 | pub shim: Ident, |
| 272 | /// The name of this static on the Rust side |
| 273 | pub rust_name: Ident, |
| 274 | /// The name of this static on the JS side |
| 275 | pub js_name: String, |
| 276 | /// Path to wasm_bindgen |
| 277 | pub wasm_bindgen: Path, |
| 278 | /// Version of `thread_local`, if any. |
| 279 | pub thread_local: Option<ThreadLocal>, |
| 280 | } |
| 281 | |
| 282 | /// Which version of the `thread_local` attribute is enabled. |
| 283 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
| 284 | pub enum ThreadLocal { |
| 285 | /// V1. |
| 286 | V1, |
| 287 | /// V2. |
| 288 | V2, |
| 289 | } |
| 290 | |
| 291 | /// The type of a static string being imported |
| 292 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 293 | #[derive (Clone)] |
| 294 | pub struct ImportString { |
| 295 | /// The visibility of this static string in Rust |
| 296 | pub vis: syn::Visibility, |
| 297 | /// The type specified by the user, which we only use to show an error if the wrong type is used. |
| 298 | pub ty: syn::Type, |
| 299 | /// The name of the shim function used to access this static |
| 300 | pub shim: Ident, |
| 301 | /// The name of this static on the Rust side |
| 302 | pub rust_name: Ident, |
| 303 | /// Path to wasm_bindgen |
| 304 | pub wasm_bindgen: Path, |
| 305 | /// Path to js_sys |
| 306 | pub js_sys: Path, |
| 307 | /// The string to export. |
| 308 | pub string: String, |
| 309 | /// Version of `thread_local`. |
| 310 | pub thread_local: ThreadLocal, |
| 311 | } |
| 312 | |
| 313 | /// The metadata for a type being imported |
| 314 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 315 | #[derive (Clone)] |
| 316 | pub struct ImportType { |
| 317 | /// The visibility of this type in Rust |
| 318 | pub vis: syn::Visibility, |
| 319 | /// The name of this type on the Rust side |
| 320 | pub rust_name: Ident, |
| 321 | /// The name of this type on the JS side |
| 322 | pub js_name: String, |
| 323 | /// The custom attributes to apply to this type |
| 324 | pub attrs: Vec<syn::Attribute>, |
| 325 | /// The TS definition to generate for this type |
| 326 | pub typescript_type: Option<String>, |
| 327 | /// The doc comment applied to this type, if one exists |
| 328 | pub doc_comment: Option<String>, |
| 329 | /// The name of the shim to check instanceof for this type |
| 330 | pub instanceof_shim: String, |
| 331 | /// The name of the remote function to use for the generated is_type_of |
| 332 | pub is_type_of: Option<syn::Expr>, |
| 333 | /// The list of classes this extends, if any |
| 334 | pub extends: Vec<syn::Path>, |
| 335 | /// A custom prefix to add and attempt to fall back to, if the type isn't found |
| 336 | pub vendor_prefixes: Vec<Ident>, |
| 337 | /// If present, don't generate a `Deref` impl |
| 338 | pub no_deref: bool, |
| 339 | /// Path to wasm_bindgen |
| 340 | pub wasm_bindgen: Path, |
| 341 | } |
| 342 | |
| 343 | /// The metadata for a String Enum |
| 344 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 345 | #[derive (Clone)] |
| 346 | pub struct StringEnum { |
| 347 | /// The Rust enum's visibility |
| 348 | pub vis: syn::Visibility, |
| 349 | /// The Rust enum's identifiers |
| 350 | pub name: Ident, |
| 351 | /// The name of this string enum in JS/TS code |
| 352 | pub js_name: String, |
| 353 | /// The Rust identifiers for the variants |
| 354 | pub variants: Vec<Ident>, |
| 355 | /// The JS string values of the variants |
| 356 | pub variant_values: Vec<String>, |
| 357 | /// The doc comments on this enum, if any |
| 358 | pub comments: Vec<String>, |
| 359 | /// Attributes to apply to the Rust enum |
| 360 | pub rust_attrs: Vec<syn::Attribute>, |
| 361 | /// Whether to generate a typescript definition for this enum |
| 362 | pub generate_typescript: bool, |
| 363 | /// Path to wasm_bindgen |
| 364 | pub wasm_bindgen: Path, |
| 365 | } |
| 366 | |
| 367 | /// Information about a function being imported or exported |
| 368 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 369 | #[derive (Clone)] |
| 370 | pub struct Function { |
| 371 | /// The name of the function |
| 372 | pub name: String, |
| 373 | /// The span of the function's name in Rust code |
| 374 | pub name_span: Span, |
| 375 | /// Whether the function has a js_name attribute |
| 376 | pub renamed_via_js_name: bool, |
| 377 | /// The arguments to the function |
| 378 | pub arguments: Vec<FunctionArgumentData>, |
| 379 | /// The data of return type of the function |
| 380 | pub ret: Option<FunctionReturnData>, |
| 381 | /// Any custom attributes being applied to the function |
| 382 | pub rust_attrs: Vec<syn::Attribute>, |
| 383 | /// The visibility of this function in Rust |
| 384 | pub rust_vis: syn::Visibility, |
| 385 | /// Whether this is an `unsafe` function |
| 386 | pub r#unsafe: bool, |
| 387 | /// Whether this is an `async` function |
| 388 | pub r#async: bool, |
| 389 | /// Whether to generate a typescript definition for this function |
| 390 | pub generate_typescript: bool, |
| 391 | /// Whether to generate jsdoc documentation for this function |
| 392 | pub generate_jsdoc: bool, |
| 393 | /// Whether this is a function with a variadict parameter |
| 394 | pub variadic: bool, |
| 395 | } |
| 396 | |
| 397 | /// Information about a function's return |
| 398 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 399 | #[derive (Clone)] |
| 400 | pub struct FunctionReturnData { |
| 401 | /// Specifies the type of the function's return |
| 402 | pub r#type: syn::Type, |
| 403 | /// Specifies the JS return type override |
| 404 | pub js_type: Option<String>, |
| 405 | /// Specifies the return description |
| 406 | pub desc: Option<String>, |
| 407 | } |
| 408 | |
| 409 | /// Information about a function's argument |
| 410 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 411 | #[derive (Clone)] |
| 412 | pub struct FunctionArgumentData { |
| 413 | /// Specifies the type of the function's argument |
| 414 | pub pat_type: syn::PatType, |
| 415 | /// Specifies the JS argument name override |
| 416 | pub js_name: Option<String>, |
| 417 | /// Specifies the JS function argument type override |
| 418 | pub js_type: Option<String>, |
| 419 | /// Specifies the argument description |
| 420 | pub desc: Option<String>, |
| 421 | } |
| 422 | |
| 423 | /// Information about a Struct being exported |
| 424 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 425 | #[derive (Clone)] |
| 426 | pub struct Struct { |
| 427 | /// The name of the struct in Rust code |
| 428 | pub rust_name: Ident, |
| 429 | /// The name of the struct in JS code |
| 430 | pub js_name: String, |
| 431 | /// All the fields of this struct to export |
| 432 | pub fields: Vec<StructField>, |
| 433 | /// The doc comments on this struct, if provided |
| 434 | pub comments: Vec<String>, |
| 435 | /// Whether this struct is inspectable (provides toJSON/toString properties to JS) |
| 436 | pub is_inspectable: bool, |
| 437 | /// Whether to generate a typescript definition for this struct |
| 438 | pub generate_typescript: bool, |
| 439 | /// Path to wasm_bindgen |
| 440 | pub wasm_bindgen: Path, |
| 441 | } |
| 442 | |
| 443 | /// The field of a struct |
| 444 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 445 | #[derive (Clone)] |
| 446 | pub struct StructField { |
| 447 | /// The name of the field in Rust code |
| 448 | pub rust_name: syn::Member, |
| 449 | /// The name of the field in JS code |
| 450 | pub js_name: String, |
| 451 | /// The name of the struct this field is part of |
| 452 | pub struct_name: Ident, |
| 453 | /// Whether this value is read-only to JS |
| 454 | pub readonly: bool, |
| 455 | /// The type of this field |
| 456 | pub ty: syn::Type, |
| 457 | /// The name of the getter shim for this field |
| 458 | pub getter: Ident, |
| 459 | /// The name of the setter shim for this field |
| 460 | pub setter: Ident, |
| 461 | /// The doc comments on this field, if any |
| 462 | pub comments: Vec<String>, |
| 463 | /// Whether to generate a typescript definition for this field |
| 464 | pub generate_typescript: bool, |
| 465 | /// Whether to generate jsdoc documentation for this field |
| 466 | pub generate_jsdoc: bool, |
| 467 | /// The span of the `#[wasm_bindgen(getter_with_clone)]` attribute applied |
| 468 | /// to this field, if any. |
| 469 | /// |
| 470 | /// If this is `Some`, the auto-generated getter for this field must clone |
| 471 | /// the field instead of copying it. |
| 472 | pub getter_with_clone: Option<Span>, |
| 473 | /// Path to wasm_bindgen |
| 474 | pub wasm_bindgen: Path, |
| 475 | } |
| 476 | |
| 477 | /// The metadata for an Enum |
| 478 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 479 | #[derive (Clone)] |
| 480 | pub struct Enum { |
| 481 | /// The name of this enum in Rust code |
| 482 | pub rust_name: Ident, |
| 483 | /// The name of this enum in JS code |
| 484 | pub js_name: String, |
| 485 | /// Whether the variant values and hole are signed, meaning that they |
| 486 | /// represent the bits of a `i32` value. |
| 487 | pub signed: bool, |
| 488 | /// The variants provided by this enum |
| 489 | pub variants: Vec<Variant>, |
| 490 | /// The doc comments on this enum, if any |
| 491 | pub comments: Vec<String>, |
| 492 | /// The value to use for a `none` variant of the enum |
| 493 | pub hole: u32, |
| 494 | /// Whether to generate a typescript definition for this enum |
| 495 | pub generate_typescript: bool, |
| 496 | /// Path to wasm_bindgen |
| 497 | pub wasm_bindgen: Path, |
| 498 | } |
| 499 | |
| 500 | /// The variant of an enum |
| 501 | #[cfg_attr (feature = "extra-traits" , derive(Debug, PartialEq, Eq))] |
| 502 | #[derive (Clone)] |
| 503 | pub struct Variant { |
| 504 | /// The name of this variant |
| 505 | pub name: Ident, |
| 506 | /// The backing value of this variant |
| 507 | pub value: u32, |
| 508 | /// The doc comments on this variant, if any |
| 509 | pub comments: Vec<String>, |
| 510 | } |
| 511 | |
| 512 | /// Unused, the type of an argument to / return from a function |
| 513 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
| 514 | pub enum TypeKind { |
| 515 | /// A by-reference arg, EG `&T` |
| 516 | ByRef, |
| 517 | /// A by-mutable-reference arg, EG `&mut T` |
| 518 | ByMutRef, |
| 519 | /// A by-value arg, EG `T` |
| 520 | ByValue, |
| 521 | } |
| 522 | |
| 523 | /// Unused, the location of a type for a function argument (import/export, argument/ret) |
| 524 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
| 525 | pub enum TypeLocation { |
| 526 | /// An imported argument (JS side type) |
| 527 | ImportArgument, |
| 528 | /// An imported return |
| 529 | ImportRet, |
| 530 | /// An exported argument (Rust side type) |
| 531 | ExportArgument, |
| 532 | /// An exported return |
| 533 | ExportRet, |
| 534 | } |
| 535 | |
| 536 | /// An enum representing either a literal value (`Lit`) or an expression (`syn::Expr`). |
| 537 | #[cfg_attr (feature = "extra-traits" , derive(Debug))] |
| 538 | #[derive (Clone)] |
| 539 | pub enum LitOrExpr { |
| 540 | /// Represents an expression that needs to be evaluated before it can be encoded |
| 541 | Expr(syn::Expr), |
| 542 | /// Represents a literal string that can be directly encoded. |
| 543 | Lit(String), |
| 544 | } |
| 545 | |
| 546 | impl Export { |
| 547 | /// Mangles a rust -> javascript export, so that the created Ident will be unique over function |
| 548 | /// name and class name, if the function belongs to a javascript class. |
| 549 | pub(crate) fn rust_symbol(&self) -> Ident { |
| 550 | let mut generated_name = String::from("__wasm_bindgen_generated" ); |
| 551 | if let Some(class) = &self.js_class { |
| 552 | generated_name.push('_' ); |
| 553 | generated_name.push_str(class); |
| 554 | } |
| 555 | generated_name.push('_' ); |
| 556 | generated_name.push_str(&self.function.name.to_string()); |
| 557 | Ident::new(&generated_name, Span::call_site()) |
| 558 | } |
| 559 | |
| 560 | /// This is the name of the shim function that gets exported and takes the raw |
| 561 | /// ABI form of its arguments and converts them back into their normal, |
| 562 | /// "high level" form before calling the actual function. |
| 563 | pub(crate) fn export_name(&self) -> String { |
| 564 | let fn_name = self.function.name.to_string(); |
| 565 | match &self.js_class { |
| 566 | Some(class) => shared::struct_function_export_name(class, &fn_name), |
| 567 | None => shared::free_function_export_name(&fn_name), |
| 568 | } |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | impl ImportKind { |
| 573 | /// Whether this type can be inside an `impl` block. |
| 574 | pub fn fits_on_impl(&self) -> bool { |
| 575 | match *self { |
| 576 | ImportKind::Function(_) => true, |
| 577 | ImportKind::Static(_) => false, |
| 578 | ImportKind::String(_) => false, |
| 579 | ImportKind::Type(_) => false, |
| 580 | ImportKind::Enum(_) => false, |
| 581 | } |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | impl Function { |
| 586 | /// If the rust object has a `fn xxx(&self) -> MyType` method, get the name for a getter in |
| 587 | /// javascript (in this case `xxx`, so you can write `val = obj.xxx`) |
| 588 | pub fn infer_getter_property(&self) -> &str { |
| 589 | &self.name |
| 590 | } |
| 591 | |
| 592 | /// If the rust object has a `fn set_xxx(&mut self, MyType)` style method, get the name |
| 593 | /// for a setter in javascript (in this case `xxx`, so you can write `obj.xxx = val`) |
| 594 | pub fn infer_setter_property(&self) -> Result<String, Diagnostic> { |
| 595 | let name: String = self.name.to_string(); |
| 596 | |
| 597 | // Otherwise we infer names based on the Rust function name. |
| 598 | if !name.starts_with("set_" ) { |
| 599 | bail_span!( |
| 600 | syn::token::Pub(self.name_span), |
| 601 | "setters must start with `set_`, found: {}" , |
| 602 | name, |
| 603 | ); |
| 604 | } |
| 605 | Ok(name[4..].to_string()) |
| 606 | } |
| 607 | } |
| 608 | |