mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-29 13:06:06 +03:00
commit
dbb498174e
@ -2,31 +2,54 @@ use proc_macro2::{Ident, Span};
|
||||
use shared;
|
||||
use syn;
|
||||
|
||||
/// An abstract syntax tree representing a rust program. Contains
|
||||
/// extra information for joining up this rust code with javascript.
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||
#[derive(Default)]
|
||||
pub struct Program {
|
||||
/// rust -> js interfaces
|
||||
pub exports: Vec<Export>,
|
||||
/// js -> rust interfaces
|
||||
pub imports: Vec<Import>,
|
||||
/// rust enums
|
||||
pub enums: Vec<Enum>,
|
||||
/// rust structs
|
||||
pub structs: Vec<Struct>,
|
||||
/// rust type aliases
|
||||
pub type_aliases: Vec<TypeAlias>,
|
||||
/// rust consts
|
||||
pub consts: Vec<Const>,
|
||||
}
|
||||
|
||||
/// A rust to js interface. Allows interaction with rust objects/functions
|
||||
/// from javascript.
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
pub struct Export {
|
||||
/// The javascript class name.
|
||||
pub class: Option<Ident>,
|
||||
/// The type of `self` (either `self`, `&self`, or `&mut self`)
|
||||
pub method_self: Option<MethodSelf>,
|
||||
/// The name of the constructor function (e.g. new).
|
||||
///
|
||||
/// This allows javascript to expose an `Object` interface, where calling
|
||||
/// the constructor maps correctly to rust.
|
||||
pub constructor: Option<String>,
|
||||
/// The rust function
|
||||
pub function: Function,
|
||||
/// Comments extracted from the rust source.
|
||||
pub comments: Vec<String>,
|
||||
/// The name of the rust function/method on the rust side.
|
||||
pub rust_name: Ident,
|
||||
}
|
||||
|
||||
/// The 3 types variations of `self`.
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
pub enum MethodSelf {
|
||||
/// `self`
|
||||
ByValue,
|
||||
/// `&mut self`
|
||||
RefMutable,
|
||||
/// `&self`
|
||||
RefShared,
|
||||
}
|
||||
|
||||
@ -219,6 +242,8 @@ impl Function {
|
||||
}
|
||||
|
||||
impl Export {
|
||||
/// Mangles a rust -> javascript export, so that the created Ident will be unique over function
|
||||
/// name and class name, if the function belongs to a javascript class.
|
||||
pub(crate) fn rust_symbol(&self) -> Ident {
|
||||
let mut generated_name = String::from("__wasm_bindgen_generated");
|
||||
if let Some(class) = &self.class {
|
||||
@ -230,6 +255,9 @@ impl Export {
|
||||
Ident::new(&generated_name, Span::call_site())
|
||||
}
|
||||
|
||||
/// This is the name of the shim function that gets exported and takes the raw
|
||||
/// ABI form of its arguments and converts them back into their normal,
|
||||
/// "high level" form before calling the actual function.
|
||||
pub(crate) fn export_name(&self) -> String {
|
||||
let fn_name = self.function.name.to_string();
|
||||
match &self.class {
|
||||
@ -310,6 +338,7 @@ impl Import {
|
||||
}
|
||||
|
||||
impl ImportKind {
|
||||
/// Whether this type can be inside an `impl` block.
|
||||
pub fn fits_on_impl(&self) -> bool {
|
||||
match *self {
|
||||
ImportKind::Function(_) => true,
|
||||
@ -330,10 +359,14 @@ impl ImportKind {
|
||||
}
|
||||
|
||||
impl ImportFunction {
|
||||
/// 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`)
|
||||
fn infer_getter_property(&self) -> String {
|
||||
self.function.name.to_string()
|
||||
}
|
||||
|
||||
/// 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`)
|
||||
fn infer_setter_property(&self) -> String {
|
||||
let name = self.function.name.to_string();
|
||||
assert!(name.starts_with("set_"), "setters must start with `set_`");
|
||||
|
@ -5,13 +5,16 @@ use quote::ToTokens;
|
||||
use shared;
|
||||
use syn;
|
||||
|
||||
/// Parsed attributes from a `#[wasm_bindgen(..)]`.
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
#[derive(Default)]
|
||||
pub struct BindgenAttrs {
|
||||
/// List of parsed attributes
|
||||
pub attrs: Vec<BindgenAttr>,
|
||||
}
|
||||
|
||||
impl BindgenAttrs {
|
||||
/// Find and parse the wasm_bindgen attributes.
|
||||
fn find(attrs: &mut Vec<syn::Attribute>) -> BindgenAttrs {
|
||||
let pos = attrs
|
||||
.iter()
|
||||
@ -34,6 +37,7 @@ impl BindgenAttrs {
|
||||
syn::parse(tt.into()).expect("malformed #[wasm_bindgen] attribute")
|
||||
}
|
||||
|
||||
/// Get the first module attribute
|
||||
fn module(&self) -> Option<&str> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -44,6 +48,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Get the first version attribute
|
||||
fn version(&self) -> Option<&str> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -54,6 +59,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Whether the catch attribute is present
|
||||
fn catch(&self) -> bool {
|
||||
self.attrs.iter().any(|a| match a {
|
||||
BindgenAttr::Catch => true,
|
||||
@ -61,6 +67,7 @@ impl BindgenAttrs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether the constructor attribute is present
|
||||
fn constructor(&self) -> bool {
|
||||
self.attrs.iter().any(|a| match a {
|
||||
BindgenAttr::Constructor => true,
|
||||
@ -68,6 +75,7 @@ impl BindgenAttrs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the first static_method_of attribute
|
||||
fn static_method_of(&self) -> Option<&Ident> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -78,6 +86,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Whether the method attributes is present
|
||||
fn method(&self) -> bool {
|
||||
self.attrs.iter().any(|a| match a {
|
||||
BindgenAttr::Method => true,
|
||||
@ -85,6 +94,7 @@ impl BindgenAttrs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the first js_namespace attribute
|
||||
fn js_namespace(&self) -> Option<&Ident> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -95,6 +105,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Get the first getter attribute
|
||||
fn getter(&self) -> Option<Option<Ident>> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -105,6 +116,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Get the first setter attribute
|
||||
fn setter(&self) -> Option<Option<Ident>> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -115,6 +127,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Whether the structural attributes is present
|
||||
fn structural(&self) -> bool {
|
||||
self.attrs.iter().any(|a| match *a {
|
||||
BindgenAttr::Structural => true,
|
||||
@ -122,6 +135,7 @@ impl BindgenAttrs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether the readonly attributes is present
|
||||
fn readonly(&self) -> bool {
|
||||
self.attrs.iter().any(|a| match *a {
|
||||
BindgenAttr::Readonly => true,
|
||||
@ -129,6 +143,7 @@ impl BindgenAttrs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the first js_name attribute
|
||||
fn js_name(&self) -> Option<&Ident> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -139,6 +154,7 @@ impl BindgenAttrs {
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Get the first js_name attribute
|
||||
fn js_class(&self) -> Option<&str> {
|
||||
self.attrs
|
||||
.iter()
|
||||
@ -165,6 +181,7 @@ impl syn::synom::Synom for BindgenAttrs {
|
||||
));
|
||||
}
|
||||
|
||||
/// The possible attributes in the `#[wasm_bindgen]`.
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
pub enum BindgenAttr {
|
||||
Catch,
|
||||
@ -258,6 +275,7 @@ impl syn::synom::Synom for BindgenAttr {
|
||||
));
|
||||
}
|
||||
|
||||
/// Consumes a `Ident` with the given name
|
||||
fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<'a, ()> {
|
||||
if let Some((ident, next)) = cursor.ident() {
|
||||
if ident == name {
|
||||
@ -267,6 +285,7 @@ fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<
|
||||
syn::parse_error()
|
||||
}
|
||||
|
||||
/// Consumes a `Ident` and returns it.
|
||||
fn term2ident<'a>(cursor: syn::buffer::Cursor<'a>) -> syn::synom::PResult<'a, Ident> {
|
||||
match cursor.ident() {
|
||||
Some(pair) => Ok(pair),
|
||||
@ -274,8 +293,16 @@ fn term2ident<'a>(cursor: syn::buffer::Cursor<'a>) -> syn::synom::PResult<'a, Id
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversion trait with context.
|
||||
///
|
||||
/// Used to convert syn tokens into an AST, that we can then use to generate glue code. The context
|
||||
/// (`Ctx`) is used to pass in the attributes from the `#[wasm_bindgen]`, if needed.
|
||||
trait ConvertToAst<Ctx> {
|
||||
/// What we are converting to.
|
||||
type Target;
|
||||
/// Convert into our target.
|
||||
///
|
||||
/// Since this is used in a procedural macro, use panic to fail.
|
||||
fn convert(self, context: Ctx) -> Self::Target;
|
||||
}
|
||||
|
||||
@ -497,6 +524,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a function (and gets the self type if appropriate) for our AST from a syn function.
|
||||
fn function_from_decl(
|
||||
name: &Ident,
|
||||
mut decl: Box<syn::FnDecl>,
|
||||
@ -556,6 +584,10 @@ fn function_from_decl(
|
||||
}
|
||||
|
||||
pub(crate) trait MacroParse<Ctx> {
|
||||
/// Parse the contents of an object into our AST, with a context if necessary.
|
||||
///
|
||||
/// The context is used to have access to the attributes on `#[wasm_bindgen]`, and to allow
|
||||
/// writing to the output `TokenStream`.
|
||||
fn macro_parse(self, program: &mut ast::Program, context: Ctx);
|
||||
}
|
||||
|
||||
@ -785,34 +817,36 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_first_ty_param(ty: Option<&syn::Type>) -> Option<Option<syn::Type>> {
|
||||
/// Get the first type parameter of a generic type, errors on incorrect input.
|
||||
fn extract_first_ty_param(ty: Option<&syn::Type>) -> Result<Option<syn::Type>, ()> {
|
||||
let t = match ty {
|
||||
Some(t) => t,
|
||||
None => return Some(None),
|
||||
None => return Ok(None),
|
||||
};
|
||||
let path = match *t {
|
||||
syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
ref path,
|
||||
}) => path,
|
||||
_ => return None,
|
||||
_ => return Err(()),
|
||||
};
|
||||
let seg = path.segments.last()?.into_value();
|
||||
let seg = path.segments.last().ok_or(())?.into_value();
|
||||
let generics = match seg.arguments {
|
||||
syn::PathArguments::AngleBracketed(ref t) => t,
|
||||
_ => return None,
|
||||
_ => return Err(()),
|
||||
};
|
||||
let ty = match *generics.args.first()?.into_value() {
|
||||
let ty = match *generics.args.first().ok_or(())?.into_value() {
|
||||
syn::GenericArgument::Type(ref t) => t,
|
||||
_ => return None,
|
||||
_ => return Err(()),
|
||||
};
|
||||
match *ty {
|
||||
syn::Type::Tuple(ref t) if t.elems.len() == 0 => return Some(None),
|
||||
syn::Type::Tuple(ref t) if t.elems.len() == 0 => return Ok(None),
|
||||
_ => {}
|
||||
}
|
||||
Some(Some(ty.clone()))
|
||||
Ok(Some(ty.clone()))
|
||||
}
|
||||
|
||||
/// Replace `Self` with the given name in `item`.
|
||||
fn replace_self(name: &Ident, item: &mut syn::ImplItem) {
|
||||
struct Walk<'a>(&'a Ident);
|
||||
|
||||
@ -854,6 +888,7 @@ fn extract_doc_comments(attrs: &[syn::Attribute]) -> Vec<String> {
|
||||
.fold(vec![], |mut acc, a| {acc.extend(a); acc})
|
||||
}
|
||||
|
||||
/// Check there are no lifetimes on the function.
|
||||
fn assert_no_lifetimes(decl: &mut syn::FnDecl) {
|
||||
struct Walk;
|
||||
|
||||
@ -869,6 +904,7 @@ fn assert_no_lifetimes(decl: &mut syn::FnDecl) {
|
||||
syn::visit_mut::VisitMut::visit_fn_decl_mut(&mut Walk, decl);
|
||||
}
|
||||
|
||||
/// If the path is a single ident, return it.
|
||||
fn extract_path_ident(path: &syn::Path) -> Option<Ident> {
|
||||
if path.leading_colon.is_some() {
|
||||
return None;
|
||||
|
@ -1,3 +1,12 @@
|
||||
//! Because some WebIDL constructs are defined in multiple places
|
||||
//! (keyword `partial` is used to add to an existing construct),
|
||||
//! We need to first walk the webidl to collect all non-partial
|
||||
//! constructs so that we have containers in which to put the
|
||||
//! partial ones.
|
||||
//!
|
||||
//! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can
|
||||
//! be partial.
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet}, mem,
|
||||
};
|
||||
@ -6,21 +15,30 @@ use webidl;
|
||||
|
||||
use super::Result;
|
||||
|
||||
/// Collection of constructs that may use partial.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct FirstPassRecord<'a> {
|
||||
pub(crate) interfaces: BTreeSet<String>,
|
||||
pub(crate) dictionaries: BTreeSet<String>,
|
||||
pub(crate) enums: BTreeSet<String>,
|
||||
/// The mixins, mapping their name to the webidl ast node for the mixin.
|
||||
pub(crate) mixins: BTreeMap<String, MixinData<'a>>,
|
||||
}
|
||||
|
||||
/// We need to collect mixin data during the first pass, to be used later.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct MixinData<'a> {
|
||||
/// The non partial mixin, if present. If there is more than one, we are
|
||||
/// parsing is a malformed WebIDL file, but the parser will recover by
|
||||
/// using the last parsed mixin.
|
||||
pub(crate) non_partial: Option<&'a webidl::ast::NonPartialMixin>,
|
||||
/// 0 or more partial mixins.
|
||||
pub(crate) partials: Vec<&'a webidl::ast::PartialMixin>,
|
||||
}
|
||||
|
||||
/// Implemented on an AST node to populate the `FirstPassRecord` struct.
|
||||
pub(crate) trait FirstPass {
|
||||
/// Populate `record` with any constructs in `self`.
|
||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()>;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,7 @@ pub fn compile(webidl_source: &str) -> Result<String> {
|
||||
Ok(compile_ast(ast))
|
||||
}
|
||||
|
||||
/// Run codegen on the AST to generate rust code.
|
||||
fn compile_ast(mut ast: backend::ast::Program) -> String {
|
||||
let mut defined = BTreeSet::from_iter(
|
||||
vec![
|
||||
@ -96,7 +97,9 @@ fn compile_ast(mut ast: backend::ast::Program) -> String {
|
||||
tokens.to_string()
|
||||
}
|
||||
|
||||
/// The main trait for parsing WebIDL AST into wasm-bindgen AST.
|
||||
trait WebidlParse<Ctx> {
|
||||
/// Parse `self` into wasm-bindgen AST, and insert it into `program`.
|
||||
fn webidl_parse(
|
||||
&self,
|
||||
program: &mut backend::ast::Program,
|
||||
|
@ -10,6 +10,7 @@ use webidl::ast::ExtendedAttribute;
|
||||
|
||||
use first_pass::FirstPassRecord;
|
||||
|
||||
/// Take a type and create an immutable shared reference to that type.
|
||||
fn shared_ref(ty: syn::Type) -> syn::Type {
|
||||
syn::TypeReference {
|
||||
and_token: Default::default(),
|
||||
@ -19,6 +20,7 @@ fn shared_ref(ty: syn::Type) -> syn::Type {
|
||||
}.into()
|
||||
}
|
||||
|
||||
/// For a webidl const type node, get the corresponding syn type node.
|
||||
pub fn webidl_const_ty_to_syn_ty(ty: &webidl::ast::ConstType) -> syn::Type {
|
||||
use webidl::ast::ConstType::*;
|
||||
|
||||
@ -39,6 +41,7 @@ pub fn webidl_const_ty_to_syn_ty(ty: &webidl::ast::ConstType) -> syn::Type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a webidl const value to the correct wasm-bindgen const value
|
||||
pub fn webidl_const_v_to_backend_const_v(v: &webidl::ast::ConstValue) -> backend::ast::ConstValue {
|
||||
match *v {
|
||||
webidl::ast::ConstValue::BooleanLiteral(b) => backend::ast::ConstValue::BooleanLiteral(b),
|
||||
@ -49,6 +52,7 @@ pub fn webidl_const_v_to_backend_const_v(v: &webidl::ast::ConstValue) -> backend
|
||||
}
|
||||
}
|
||||
|
||||
/// From `ident` and `Ty`, create `ident: Ty` for use in e.g. `fn(ident: Ty)`.
|
||||
fn simple_fn_arg(ident: Ident, ty: syn::Type) -> syn::ArgCaptured {
|
||||
syn::ArgCaptured {
|
||||
pat: syn::Pat::Ident(syn::PatIdent {
|
||||
@ -62,6 +66,7 @@ fn simple_fn_arg(ident: Ident, ty: syn::Type) -> syn::ArgCaptured {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create `()`.
|
||||
fn unit_ty() -> syn::Type {
|
||||
syn::Type::Tuple(syn::TypeTuple {
|
||||
paren_token: Default::default(),
|
||||
@ -69,6 +74,7 @@ fn unit_ty() -> syn::Type {
|
||||
})
|
||||
}
|
||||
|
||||
/// From `T` create `Result<T, ::wasm_bindgen::JsValue>`.
|
||||
fn result_ty(t: syn::Type) -> syn::Type {
|
||||
let js_value = leading_colon_path_ty(vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")]);
|
||||
|
||||
@ -89,6 +95,7 @@ fn result_ty(t: syn::Type) -> syn::Type {
|
||||
ty.into()
|
||||
}
|
||||
|
||||
/// From `T` create `[T]`.
|
||||
fn slice_ty(t: syn::Type) -> syn::Type {
|
||||
syn::TypeSlice {
|
||||
bracket_token: Default::default(),
|
||||
@ -96,6 +103,7 @@ fn slice_ty(t: syn::Type) -> syn::Type {
|
||||
}.into()
|
||||
}
|
||||
|
||||
/// From `T` create `Vec<T>`.
|
||||
fn vec_ty(t: syn::Type) -> syn::Type {
|
||||
let arguments = syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
@ -113,6 +121,7 @@ fn vec_ty(t: syn::Type) -> syn::Type {
|
||||
ty.into()
|
||||
}
|
||||
|
||||
/// Possible positions for a type in a function signature.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum TypePosition {
|
||||
Argument,
|
||||
@ -120,11 +129,14 @@ pub enum TypePosition {
|
||||
}
|
||||
|
||||
impl<'a> FirstPassRecord<'a> {
|
||||
/// Use information from the first pass to work out the correct Rust type to use for
|
||||
/// a given WebIDL type.
|
||||
pub fn webidl_ty_to_syn_ty(
|
||||
&self,
|
||||
ty: &webidl::ast::Type,
|
||||
pos: TypePosition,
|
||||
) -> Option<syn::Type> {
|
||||
// Array type is borrowed for arguments (`&[T]`) and owned for return value (`Vec<T>`).
|
||||
let array = |base_ty: &str| {
|
||||
match pos {
|
||||
TypePosition::Argument => {
|
||||
@ -220,6 +232,8 @@ impl<'a> FirstPassRecord<'a> {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
// Map nullable to an option.
|
||||
if ty.nullable {
|
||||
let arguments = syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
@ -240,6 +254,10 @@ impl<'a> FirstPassRecord<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Use the first pass to convert webidl function arguments to rust arguments.
|
||||
///
|
||||
/// `kind` is whether the function is a method, in which case we would need a `self`
|
||||
/// parameter.
|
||||
fn webidl_arguments_to_syn_arg_captured<'b, I>(
|
||||
&self,
|
||||
arguments: I,
|
||||
@ -284,6 +302,7 @@ impl<'a> FirstPassRecord<'a> {
|
||||
Some(res)
|
||||
}
|
||||
|
||||
/// Create a wasm-bindgen function, if possible.
|
||||
pub fn create_function<'b, I>(
|
||||
&self,
|
||||
name: &str,
|
||||
@ -333,6 +352,7 @@ impl<'a> FirstPassRecord<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a wasm-bindgen method, if possible.
|
||||
pub fn create_basic_method(
|
||||
&self,
|
||||
arguments: &[webidl::ast::Argument],
|
||||
@ -384,6 +404,7 @@ impl<'a> FirstPassRecord<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a wasm-bindgen getter method, if possible.
|
||||
pub fn create_getter(
|
||||
&self,
|
||||
name: &str,
|
||||
@ -413,6 +434,7 @@ impl<'a> FirstPassRecord<'a> {
|
||||
self.create_function(name, iter::empty(), ret, kind, is_structural, catch)
|
||||
}
|
||||
|
||||
/// Create a wasm-bindgen setter method, if possible.
|
||||
pub fn create_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
@ -442,6 +464,7 @@ impl<'a> FirstPassRecord<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for an attribute by name in some webidl object's attributes.
|
||||
fn has_named_attribute(ext_attrs: &[Box<ExtendedAttribute>], attribute: &str) -> bool {
|
||||
ext_attrs.iter().any(|attr| match &**attr {
|
||||
ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) => {
|
||||
@ -456,10 +479,12 @@ pub fn is_chrome_only(ext_attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
has_named_attribute(ext_attrs, "ChromeOnly")
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as a no interface object.
|
||||
pub fn is_no_interface_object(ext_attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
has_named_attribute(ext_attrs, "NoInterfaceObject")
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as structural.
|
||||
pub fn is_structural(attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
attrs.iter().any(|attr| match &**attr {
|
||||
ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) => {
|
||||
@ -469,6 +494,7 @@ pub fn is_structural(attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as throwing.
|
||||
pub fn throws(attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
attrs.iter().any(|attr| match &**attr {
|
||||
ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) => name == "Throws",
|
||||
@ -476,6 +502,7 @@ pub fn throws(attrs: &[Box<ExtendedAttribute>]) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a syn `pub` token
|
||||
pub fn public() -> syn::Visibility {
|
||||
syn::Visibility::Public(syn::VisPublic {
|
||||
pub_token: Default::default(),
|
||||
|
Loading…
Reference in New Issue
Block a user