diff --git a/crates/webidl/src/first_pass.rs b/crates/webidl/src/first_pass.rs index 01ff5165..e9c60e48 100644 --- a/crates/webidl/src/first_pass.rs +++ b/crates/webidl/src/first_pass.rs @@ -15,7 +15,6 @@ use weedle::argument::Argument; use weedle::attribute::*; use weedle::interface::*; use weedle::mixin::*; -use weedle::namespace::OperationNamespaceMember; use weedle; use super::Result; @@ -43,12 +42,9 @@ pub(crate) struct InterfaceData<'src> { pub(crate) global: bool, pub(crate) attributes: Vec<&'src AttributeInterfaceMember<'src>>, pub(crate) consts: Vec<&'src ConstMember<'src>>, - pub(crate) methods: Vec<&'src OperationInterfaceMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, - pub(crate) operations2: BTreeMap, OperationData2<'src>>, pub(crate) superclass: Option<&'src str>, pub(crate) definition_attributes: Option<&'src [ExtendedAttribute<'src>]>, - pub(crate) constructors: Vec<(&'src str, &'src [Argument<'src>])>, } /// We need to collect mixin data during the first pass, to be used later. @@ -58,18 +54,14 @@ pub(crate) struct MixinData<'src> { pub(crate) partial: bool, pub(crate) attributes: Vec<&'src AttributeMixinMember<'src>>, pub(crate) consts: Vec<&'src ConstMember<'src>>, - pub(crate) methods: Vec<&'src OperationMixinMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, - pub(crate) operations2: BTreeMap, OperationData2<'src>>, } /// We need to collect namespace data during the first pass, to be used later. #[derive(Default)] pub(crate) struct NamespaceData<'src> { /// Whether only partial namespaces were encountered - pub(crate) members: Vec<&'src OperationNamespaceMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, - pub(crate) operations2: BTreeMap, OperationData2<'src>>, } #[derive(Default)] @@ -90,13 +82,6 @@ pub(crate) enum OperationId<'src> { #[derive(Default)] pub(crate) struct OperationData<'src> { - pub(crate) overloaded: bool, - /// Map from argument names to whether they are the same for multiple overloads - pub(crate) argument_names_same: BTreeMap, bool>, -} - -#[derive(Default)] -pub(crate) struct OperationData2<'src> { pub(crate) signatures: Vec>, pub(crate) is_static: bool, } @@ -234,9 +219,9 @@ fn first_pass_operation<'src>( ret: &weedle::types::ReturnType<'src>, attrs: &'src Option>, is_static: bool, -) -> bool { +) { if util::is_chrome_only(attrs) { - return false + return } let mut names = Vec::with_capacity(arguments.len()); @@ -246,27 +231,27 @@ fn first_pass_operation<'src>( Argument::Variadic(variadic) => names.push(variadic.identifier.0), } } - let (operations, operations2) = match first_pass_operation_type{ + let operations = match first_pass_operation_type{ FirstPassOperationType::Interface => { let x = record .interfaces .get_mut(self_name) .expect(&format!("not found {} interface", self_name)); - (&mut x.operations, &mut x.operations2) + &mut x.operations }, FirstPassOperationType::Mixin => { let x = record .mixins .get_mut(self_name) .expect(&format!("not found {} mixin", self_name)); - (&mut x.operations, &mut x.operations2) + &mut x.operations }, FirstPassOperationType::Namespace => { let x = record .namespaces .get_mut(self_name) .expect(&format!("not found {} namespace", self_name)); - (&mut x.operations, &mut x.operations2) + &mut x.operations }, }; let mut args = Vec::with_capacity(arguments.len()); @@ -277,7 +262,7 @@ fn first_pass_operation<'src>( warn!("Unsupported variadic argument {} in {}", v.identifier.0, self_name); - return false + return } }; args.push(Arg { @@ -287,23 +272,14 @@ fn first_pass_operation<'src>( }); } for id in ids { - operations - .entry(*id) - .and_modify(|operation_data| operation_data.overloaded = true) - .or_default() - .argument_names_same - .entry(names.clone()) - .and_modify(|same_argument_names| *same_argument_names = true) - .or_insert(false); - let op2 = operations2.entry(*id).or_default(); - op2.is_static = is_static; - op2.signatures.push(Signature { + let op = operations.entry(*id).or_default(); + op.is_static = is_static; + op.signatures.push(Signature { args: args.clone(), ret: ret.clone(), attrs, }); } - true } impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> { @@ -360,7 +336,7 @@ fn process_interface_attribute<'src>( ExtendedAttribute::ArgList(list) if list.identifier.0 == "Constructor" => { - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Interface, self_name, @@ -369,16 +345,10 @@ fn process_interface_attribute<'src>( &return_ty, &None, false, - ) { - record.interfaces - .get_mut(self_name) - .unwrap() - .constructors - .push((self_name, &list.args.body.list)); - } + ); } ExtendedAttribute::NoArgs(other) if (other.0).0 == "Constructor" => { - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Interface, self_name, @@ -387,18 +357,12 @@ fn process_interface_attribute<'src>( &return_ty, &None, false, - ) { - record.interfaces - .get_mut(self_name) - .unwrap() - .constructors - .push((self_name, &[])); - } + ); } ExtendedAttribute::NamedArgList(list) if list.lhs_identifier.0 == "NamedConstructor" => { - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Interface, self_name, @@ -407,13 +371,7 @@ fn process_interface_attribute<'src>( &return_ty, &None, false, - ) { - record.interfaces - .get_mut(self_name) - .unwrap() - .constructors - .push((list.rhs_identifier.0, &list.args.body.list)); - } + ); } ExtendedAttribute::Ident(id) if id.lhs_identifier.0 == "Global" => { record.interfaces.get_mut(self_name).unwrap().global = true; @@ -511,7 +469,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceM Special::LegacyCaller(_) => continue, }); } - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Interface, self_name, @@ -520,13 +478,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceM &self.return_type, &self.attributes, is_static, - ) { - record.interfaces - .get_mut(self_name) - .unwrap() - .methods - .push(self); - } + ); Ok(()) } } @@ -623,7 +575,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'s return Ok(()) } - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Mixin, self_name, @@ -632,13 +584,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'s &self.return_type, &self.attributes, false, - ) { - record.mixins - .get_mut(self_name) - .unwrap() - .methods - .push(self); - } + ); Ok(()) } } @@ -722,7 +668,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::namespace::NamespaceMember<'sr impl<'src> FirstPass<'src, &'src str> for weedle::namespace::OperationNamespaceMember<'src> { fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> { - if first_pass_operation( + first_pass_operation( record, FirstPassOperationType::Namespace, self_name, @@ -731,9 +677,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::namespace::OperationNamespaceM &self.return_type, &self.attributes, true, - ) { - record.namespaces.get_mut(self_name).unwrap().members.push(self); - } + ); Ok(()) } } diff --git a/crates/webidl/src/idl_type.rs b/crates/webidl/src/idl_type.rs index 3992b20d..4942df4e 100644 --- a/crates/webidl/src/idl_type.rs +++ b/crates/webidl/src/idl_type.rs @@ -596,88 +596,3 @@ fn idl_type_flatten_test() { ], ); } - -/// Converts arguments into possibilities. -/// -/// Each argument represented with a tuple of its idl type and whether it is optional. -/// Each possibility is a vector of idl types. -/// -/// The goal is to find equivalent possibilities of argument types each of which is not optional and -/// does not contains union types. -pub(crate) fn flatten<'a>(arguments: &'a [(IdlType, bool)]) -> Vec>> { - if arguments.is_empty() { - return vec![Vec::new()]; - } - let mut optional_possibilities = if arguments[0].1 { vec![Vec::new()] } else { Vec::new() }; - let mut possibilities = Vec::new(); - for idl_type in arguments[0].0.flatten() { - possibilities.push(vec![idl_type]) - } - for argument in arguments[1..].iter() { - let mut new_possibilities = Vec::new(); - for old_idl_types in possibilities { - if argument.1 { - optional_possibilities.push(old_idl_types.clone()); - } - for idl_type in argument.0.flatten() { - let mut new_idl_types = old_idl_types.clone(); - new_idl_types.push(idl_type); - new_possibilities.push(new_idl_types) - } - } - possibilities = new_possibilities; - } - optional_possibilities.extend(possibilities.into_iter()); - optional_possibilities -} - -#[test] -fn arguments_flatten_test() { - use self::IdlType::*; - - assert_eq!( - flatten( - &vec![ - ( - Union(vec![ - Short, - Long, - ]), - false, - ), - ( - Union(vec![ - Sequence(Box::new( - Union(vec![ - Byte, - Octet, - ]), - )), - LongLong, - ]), - true, - ), - ( - DomString, - true, - ) - ] - ), - vec![ - vec![Short], - vec![Long], - vec![Short, Sequence(Box::new(Byte))], - vec![Short, Sequence(Box::new(Octet))], - vec![Short, LongLong], - vec![Long, Sequence(Box::new(Byte))], - vec![Long, Sequence(Box::new(Octet))], - vec![Long, LongLong], - vec![Short, Sequence(Box::new(Byte)), DomString], - vec![Short, Sequence(Box::new(Octet)), DomString], - vec![Short, LongLong, DomString], - vec![Long, Sequence(Box::new(Byte)), DomString], - vec![Long, Sequence(Box::new(Octet)), DomString], - vec![Long, LongLong, DomString] - ], - ); -} diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 652c2bbe..0df6dc20 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -43,14 +43,13 @@ use backend::util::{ident_ty, rust_ident, raw_ident, wrap_import_function}; use failure::ResultExt; use heck::{ShoutySnakeCase, SnakeCase}; use proc_macro2::{Ident, Span}; -use weedle::argument::Argument; use weedle::attribute::{ExtendedAttributeList}; use weedle::dictionary::DictionaryMember; use first_pass::{FirstPass, FirstPassRecord, OperationId, InterfaceData}; -use first_pass::OperationData2; +use first_pass::OperationData; use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, mdn_doc}; -use idl_type::{IdlType, ToIdlType}; +use idl_type::ToIdlType; pub use error::{Error, ErrorKind, Result}; @@ -298,7 +297,7 @@ impl<'src> FirstPassRecord<'src> { imports: Default::default(), }; - for (id, data) in ns.operations2.iter() { + for (id, data) in ns.operations.iter() { self.append_ns_member(&mut module, name, id, data); } @@ -310,7 +309,7 @@ impl<'src> FirstPassRecord<'src> { module: &mut backend::ast::Module, self_name: &'src str, id: &OperationId<'src>, - data: &OperationData2<'src>, + data: &OperationData<'src>, ) { let name = match id { OperationId::Operation(Some(name)) => name, @@ -404,14 +403,8 @@ impl<'src> FirstPassRecord<'src> { }), }); - // 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 - // } - self.member_operation2(program, name, data, id, op_data); + for (id, op_data) in data.operations.iter() { + self.member_operation(program, name, data, id, op_data); } for member in data.consts.iter() { self.append_const(program, name, member); @@ -429,8 +422,8 @@ impl<'src> FirstPassRecord<'src> { } for mixin_data in self.all_mixins(name) { - for (id, op_data) in mixin_data.operations2.iter() { - self.member_operation2(program, name, data, id, op_data); + for (id, op_data) in mixin_data.operations.iter() { + self.member_operation(program, name, data, id, op_data); } for member in &mixin_data.consts { self.append_const(program, name, member); @@ -453,62 +446,6 @@ 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 member_attribute( &self, program: &mut backend::ast::Program, @@ -563,13 +500,13 @@ impl<'src> FirstPassRecord<'src> { } } - fn member_operation2( + fn member_operation( &self, program: &mut backend::ast::Program, self_name: &str, data: &InterfaceData<'src>, id: &OperationId<'src>, - op_data: &OperationData2<'src>, + op_data: &OperationData<'src>, ) { let import_function_kind = |opkind| { self.import_function_kind(self_name, data.global, op_data.is_static, opkind) diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index 20c4c262..b4615ced 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -1,4 +1,3 @@ -use std::collections::BTreeMap; use std::iter::FromIterator; use std::ptr; @@ -9,11 +8,10 @@ use proc_macro2::Ident; use syn; use weedle; use weedle::attribute::{ExtendedAttributeList, ExtendedAttribute}; -use weedle::argument::Argument; use weedle::literal::{ConstValue, FloatLit, IntegerLit}; -use first_pass::{self, FirstPassRecord, OperationId, OperationData2, Signature}; -use idl_type::{IdlType, ToIdlType, flatten}; +use first_pass::{FirstPassRecord, OperationId, OperationData, Signature}; +use idl_type::{IdlType, ToIdlType}; /// Take a type and create an immutable shared reference to that type. pub(crate) fn shared_ref(ty: syn::Type) -> syn::Type { @@ -197,94 +195,6 @@ pub enum TypePosition { } impl<'src> FirstPassRecord<'src> { - /// Create a wasm-bindgen function, if possible. - pub fn create_function( - &self, - name: &str, - overloaded: bool, - same_argument_names: bool, - arguments: &[(&str, IdlType<'src>, bool)], - ret: IdlType<'src>, - kind: backend::ast::ImportFunctionKind, - structural: bool, - catch: bool, - doc_comment: Option, - ) -> Vec { - let rust_name = if overloaded && !arguments.is_empty() { - let mut argument_type_names = String::new(); - for argument in arguments { - if argument_type_names.len() > 0 { - argument_type_names.push_str("_and_"); - } - if same_argument_names { - argument.1.push_type_name(&mut argument_type_names); - } else { - argument_type_names.push_str(&argument.0.to_snake_case()); - } - } - if name == "new" { - "with_".to_owned() + &argument_type_names - } else { - name.to_snake_case() + "_with_" + &argument_type_names - } - } else { - name.to_snake_case() - }; - - let converted_arguments = arguments - .iter() - .cloned() - .map(|(_name, idl_type, optional)| (idl_type, optional)) - .collect::>(); - let possibilities = flatten(&converted_arguments); - let mut arguments_count_multiple = BTreeMap::new(); - for idl_types in &possibilities { - arguments_count_multiple - .entry(idl_types.len()) - .and_modify(|variants_count| { *variants_count = true; }) - .or_insert(false); - } - let mut import_functions = Vec::new(); - 'outer: for idl_types in &possibilities { - let rust_name = if possibilities.len() > 1 { - let mut rust_name = rust_name.clone(); - let mut first = true; - let iter = arguments.iter().zip(idl_types).enumerate(); - for (i, ((argument_name, _, _), idl_type)) in iter { - if possibilities.iter().all(|p| p.get(i) == Some(idl_type)) { - continue - } - if first { - rust_name.push_str("_with_"); - first = false; - } else { - rust_name.push_str("_and_"); - } - if arguments_count_multiple[&idl_types.len()] { - idl_type.push_type_name(&mut rust_name); - } else { - rust_name.push_str(&argument_name.to_snake_case()); - } - } - rust_name - } else { - rust_name.clone() - }; - let f = self.create_one_function( - name, - &rust_name, - arguments.iter().map(|s| s.0).zip(idl_types), - &ret, - kind.clone(), - structural, - catch, - doc_comment.clone(), - ); - import_functions.extend(f); - } - import_functions - } - pub fn create_one_function<'a>( &self, js_name: &str, @@ -382,94 +292,6 @@ impl<'src> FirstPassRecord<'src> { }) } - /// Convert arguments to ones suitable crating function - pub(crate) fn convert_arguments( - &self, - arguments: &[weedle::argument::Argument<'src>], - ) -> Option, bool)>> { - let mut converted_arguments = Vec::with_capacity(arguments.len()); - for argument in arguments { - let name = match argument { - Argument::Single(single) => single.identifier.0, - Argument::Variadic(variadic) => variadic.identifier.0, - }; - let ty = match argument { - Argument::Single(single) => &single.type_.type_, - Argument::Variadic(variadic) => &variadic.type_, - }; - let idl_type = ty.to_idl_type(self)?; - let optional = match argument { - Argument::Single(single) => single.optional.is_some(), - Argument::Variadic(_variadic) => false, - }; - converted_arguments.push((name, idl_type, optional)); - } - Some(converted_arguments) - } - - /// Whether operation is overloaded and - /// whether there overloads with same argument names for given argument types - pub fn get_operation_overloading( - &self, - arguments: &[Argument], - operation_id: &first_pass::OperationId, - self_name: &str, - namespace: bool, - ) -> (bool, bool) { - fn get_operation_data<'src>( - record: &'src FirstPassRecord, - operation_id: &'src ::first_pass::OperationId, - self_name: &str, - mixin_name: &str, - ) -> Option<&'src ::first_pass::OperationData<'src>> { - if let Some(mixin_data) = record.mixins.get(mixin_name) { - if let Some(operation_data) = mixin_data.operations.get(operation_id) { - return Some(operation_data); - } - } - if let Some(mixin_names) = record.includes.get(mixin_name) { - for mixin_name in mixin_names { - if let Some(operation_data) = get_operation_data(record, operation_id, self_name, mixin_name) { - return Some(operation_data); - } - } - } - None - } - - let operation_data = if !namespace { - self - .interfaces - .get(self_name) - .and_then(|interface_data| interface_data.operations.get(operation_id)) - .unwrap_or_else(|| - get_operation_data(self, operation_id, self_name, self_name) - .expect(&format!("not found operation {:?} in interface {}", operation_id, self_name)) - ) - } else { - self - .namespaces - .get(self_name) - .and_then(|interface_data| interface_data.operations.get(operation_id)) - .expect(&format!("not found operation {:?} in namespace {}", operation_id, self_name)) - }; - - let mut names = Vec::with_capacity(arguments.len()); - for argument in arguments { - match argument { - Argument::Single(single) => names.push(single.identifier.0), - Argument::Variadic(variadic) => names.push(variadic.identifier.0), - } - } - ( - operation_data.overloaded, - *operation_data - .argument_names_same - .get(&names) - .unwrap_or(&false) - ) - } - /// Create a wasm-bindgen getter method, if possible. pub fn create_getter( &self, @@ -552,7 +374,7 @@ impl<'src> FirstPassRecord<'src> { &self, kind: backend::ast::ImportFunctionKind, id: &OperationId<'src>, - data: &OperationData2<'src>, + data: &OperationData<'src>, ) -> Vec { diff --git a/examples/julia_set/Cargo.toml b/examples/julia_set/Cargo.toml index f6b0dbdb..509b6cc8 100644 --- a/examples/julia_set/Cargo.toml +++ b/examples/julia_set/Cargo.toml @@ -8,4 +8,3 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../.." } -web-sys = { path = "../../crates/web-sys" } diff --git a/examples/julia_set/src/lib.rs b/examples/julia_set/src/lib.rs index 2d9e6ac1..a92eea48 100644 --- a/examples/julia_set/src/lib.rs +++ b/examples/julia_set/src/lib.rs @@ -1,13 +1,18 @@ extern crate wasm_bindgen; -extern crate web_sys; - use wasm_bindgen::prelude::*; -use web_sys::{CanvasRenderingContext2D, ImageData}; mod fractal; use fractal::get_julia_set; use fractal::complex::Complex; +#[wasm_bindgen] +extern "C" { + pub type ImageData; + + #[wasm_bindgen(constructor)] + pub fn new(arr: &Uint8ClampedArray, width: u32, height: u32) -> ImageData; +} + #[wasm_bindgen] extern "C" { pub type Uint8ClampedArray; @@ -16,13 +21,19 @@ extern "C" { pub fn new(arr: &[u8]) -> Uint8ClampedArray; } +#[wasm_bindgen] +extern "C" { + pub type CanvasRenderingContext2D; + + #[wasm_bindgen(method, js_name = putImageData)] + pub fn put_image_data(this: &CanvasRenderingContext2D, image_data: &ImageData, p_1: i32, p_2: i32); +} + #[wasm_bindgen] pub fn draw(ctx: &CanvasRenderingContext2D, width: u32, height: u32, real: f64, imaginary: f64) { let c = Complex { real, imaginary }; let data = get_julia_set(width, height, c); let uint8_array = Uint8ClampedArray::new(&data); - ctx.put_image_data( - &ImageData::with_data_and_sw_and_sh_with_sh(&data, width, height).unwrap(), - 0.0, 0.0); + ctx.put_image_data(&ImageData::new(&uint8_array, width, height), 0, 0); }