diff --git a/crates/webidl/src/first_pass.rs b/crates/webidl/src/first_pass.rs index c4ebc7fa4..01ff51656 100644 --- a/crates/webidl/src/first_pass.rs +++ b/crates/webidl/src/first_pass.rs @@ -7,6 +7,7 @@ //! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can //! be partial. +use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use weedle::{DictionaryDefinition, PartialDictionaryDefinition}; @@ -80,7 +81,7 @@ pub(crate) struct DictionaryData<'src> { #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] pub(crate) enum OperationId<'src> { - Constructor, + Constructor(IgnoreTraits<&'src str>), Operation(Option<&'src str>), IndexingGetter, IndexingSetter, @@ -363,7 +364,7 @@ fn process_interface_attribute<'src>( record, FirstPassOperationType::Interface, self_name, - &[OperationId::Constructor], + &[OperationId::Constructor(IgnoreTraits(self_name))], &list.args.body.list, &return_ty, &None, @@ -381,7 +382,7 @@ fn process_interface_attribute<'src>( record, FirstPassOperationType::Interface, self_name, - &[OperationId::Constructor], + &[OperationId::Constructor(IgnoreTraits(self_name))], &[], &return_ty, &None, @@ -401,7 +402,7 @@ fn process_interface_attribute<'src>( record, FirstPassOperationType::Interface, self_name, - &[OperationId::Constructor], + &[OperationId::Constructor(IgnoreTraits(list.rhs_identifier.0))], &list.args.body.list, &return_ty, &None, @@ -784,3 +785,24 @@ impl<'a> FirstPassRecord<'a> { } } } + +#[derive(Copy, Clone, Debug)] +pub struct IgnoreTraits(pub T); + +impl PartialEq for IgnoreTraits { + fn eq(&self, _other: &IgnoreTraits) -> bool { true } +} + +impl Eq for IgnoreTraits {} + +impl PartialOrd for IgnoreTraits { + fn partial_cmp(&self, _other: &IgnoreTraits) -> Option { + Some(Ordering::Equal) + } +} + +impl Ord for IgnoreTraits { + fn cmp(&self, _other: &IgnoreTraits) -> Ordering { + Ordering::Equal + } +} diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 438ffb741..652c2bbe4 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -314,7 +314,7 @@ impl<'src> FirstPassRecord<'src> { ) { let name = match id { OperationId::Operation(Some(name)) => name, - OperationId::Constructor | + OperationId::Constructor(_) | OperationId::Operation(None) | OperationId::IndexingGetter | OperationId::IndexingSetter | @@ -404,13 +404,13 @@ impl<'src> FirstPassRecord<'src> { }), }); - for (ctor_name, args) in data.constructors.iter() { - self.append_constructor(program, name, ctor_name, args); - } + // for (ctor_name, args) in data.constructors.iter() { + // self.append_constructor(program, name, ctor_name, args); + // } for (id, op_data) in data.operations2.iter() { - if let OperationId::Constructor = id { - continue // TODO - } + // if let OperationId::Constructor = id { + // continue // TODO + // } self.member_operation2(program, name, data, id, op_data); } for member in data.consts.iter() { @@ -453,61 +453,61 @@ impl<'src> FirstPassRecord<'src> { } } - fn append_constructor( - &self, - program: &mut backend::ast::Program, - iface_name: &'src str, - ctor_name: &'src str, - args: &[Argument<'src>], - ) { - let (overloaded, same_argument_names) = self.get_operation_overloading( - args, - &::first_pass::OperationId::Constructor, - iface_name, - false, - ); - - let self_ty = ident_ty(rust_ident(camel_case_ident(iface_name).as_str())); - - let kind = backend::ast::ImportFunctionKind::Method { - class: ctor_name.to_string(), - ty: self_ty.clone(), - kind: backend::ast::MethodKind::Constructor, - }; - - let structural = false; - - // Constructors aren't annotated with `[Throws]` extended attributes - // (how could they be, since they themselves are extended - // attributes?) so we must conservatively assume that they can - // always throw. - // - // From https://heycam.github.io/webidl/#Constructor (emphasis - // mine): - // - // > The prose definition of a constructor must either return an IDL - // > value of a type corresponding to the interface the - // > `[Constructor]` extended attribute appears on, **or throw an - // > exception**. - let throws = true; - - for import_function in self.create_function( - "new", - overloaded, - same_argument_names, - &match self.convert_arguments(args) { - Some(arguments) => arguments, - None => return, - }, - IdlType::Interface(iface_name), - kind, - structural, - throws, - None, - ) { - program.imports.push(wrap_import_function(import_function)); - } - } + // fn append_constructor( + // &self, + // program: &mut backend::ast::Program, + // iface_name: &'src str, + // ctor_name: &'src str, + // args: &[Argument<'src>], + // ) { + // let (overloaded, same_argument_names) = self.get_operation_overloading( + // args, + // &::first_pass::OperationId::Constructor, + // iface_name, + // false, + // ); + // + // let self_ty = ident_ty(rust_ident(camel_case_ident(iface_name).as_str())); + // + // let kind = backend::ast::ImportFunctionKind::Method { + // class: ctor_name.to_string(), + // ty: self_ty.clone(), + // kind: backend::ast::MethodKind::Constructor, + // }; + // + // let structural = false; + // + // // Constructors aren't annotated with `[Throws]` extended attributes + // // (how could they be, since they themselves are extended + // // attributes?) so we must conservatively assume that they can + // // always throw. + // // + // // From https://heycam.github.io/webidl/#Constructor (emphasis + // // mine): + // // + // // > The prose definition of a constructor must either return an IDL + // // > value of a type corresponding to the interface the + // // > `[Constructor]` extended attribute appears on, **or throw an + // // > exception**. + // let throws = true; + // + // for import_function in self.create_function( + // "new", + // overloaded, + // same_argument_names, + // &match self.convert_arguments(args) { + // Some(arguments) => arguments, + // None => return, + // }, + // IdlType::Interface(iface_name), + // kind, + // structural, + // throws, + // None, + // ) { + // program.imports.push(wrap_import_function(import_function)); + // } + // } fn member_attribute( &self, @@ -571,28 +571,29 @@ impl<'src> FirstPassRecord<'src> { id: &OperationId<'src>, op_data: &OperationData2<'src>, ) { - let operation_kind = match id { - OperationId::Constructor => panic!("constructors are unsupported"), - OperationId::Operation(_) => backend::ast::OperationKind::Regular, - OperationId::IndexingGetter => backend::ast::OperationKind::IndexingGetter, - OperationId::IndexingSetter => backend::ast::OperationKind::IndexingSetter, - OperationId::IndexingDeleter => backend::ast::OperationKind::IndexingDeleter, + let import_function_kind = |opkind| { + self.import_function_kind(self_name, data.global, op_data.is_static, opkind) }; - let operation = backend::ast::Operation { - is_static: op_data.is_static, - kind: operation_kind, - }; - let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str())); - let kind = if data.global { - backend::ast::ImportFunctionKind::ScopedMethod { - ty, - operation, + let kind = match id { + OperationId::Constructor(ctor_name) => { + let self_ty = ident_ty(rust_ident(&camel_case_ident(self_name))); + backend::ast::ImportFunctionKind::Method { + class: ctor_name.0.to_string(), + ty: self_ty.clone(), + kind: backend::ast::MethodKind::Constructor, + } } - } else { - backend::ast::ImportFunctionKind::Method { - class: self_name.to_string(), - ty, - kind: backend::ast::MethodKind::Operation(operation), + OperationId::Operation(_) => { + import_function_kind(backend::ast::OperationKind::Regular) + } + OperationId::IndexingGetter => { + import_function_kind(backend::ast::OperationKind::IndexingGetter) + } + OperationId::IndexingSetter => { + import_function_kind(backend::ast::OperationKind::IndexingSetter) + } + OperationId::IndexingDeleter => { + import_function_kind(backend::ast::OperationKind::IndexingDeleter) } }; for method in self.create_imports(kind, id, op_data) { diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index 9ff2582b2..20c4c2627 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -522,7 +522,7 @@ impl<'src> FirstPassRecord<'src> { ) } - fn import_function_kind( + pub fn import_function_kind( &self, self_name: &str, global: bool, @@ -630,16 +630,28 @@ impl<'src> FirstPassRecord<'src> { } } - let (name, force_structural) = match id { - OperationId::Constructor => ("new", false), - OperationId::Operation(Some(s)) => (*s, false), + let (name, force_structural, force_throws) = match id { + // Constructors aren't annotated with `[Throws]` extended attributes + // (how could they be, since they themselves are extended + // attributes?) so we must conservatively assume that they can + // always throw. + // + // From https://heycam.github.io/webidl/#Constructor (emphasis + // mine): + // + // > The prose definition of a constructor must either return an IDL + // > value of a type corresponding to the interface the + // > `[Constructor]` extended attribute appears on, **or throw an + // > exception**. + OperationId::Constructor(_) => ("new", false, true), + OperationId::Operation(Some(s)) => (*s, false, false), OperationId::Operation(None) => { warn!("unsupported unnamed operation"); return Vec::new() } - OperationId::IndexingGetter => ("get", true), - OperationId::IndexingSetter => ("set", true), - OperationId::IndexingDeleter => ("delete", true), + OperationId::IndexingGetter => ("get", true, false), + OperationId::IndexingSetter => ("set", true, false), + OperationId::IndexingDeleter => ("delete", true, false), }; let mut ret = Vec::new(); @@ -707,7 +719,7 @@ impl<'src> FirstPassRecord<'src> { &ret_ty, kind.clone(), force_structural || is_structural(&signature.orig.attrs), - throws(&signature.orig.attrs), + force_throws || throws(&signature.orig.attrs), None, )); }